CAF: malloc(): memory corruption

瀏覽次數:26 次
跳到第一則未讀訊息

Hanie Rahmati

未讀,
2020年7月18日 清晨7:03:272020/7/18
收件者:actor-framework
Hello everyone,

I'm going to write a program containing two actors and one of them has access to the other ones. I defined one of them as class-based actor which is the main component and other one as function-based actor. I followed the structure of dining philosopher example. I defined some vectors in namespace domain which I guess they will be considered global variables and function-based actor will use them.

First, I need to know the way I choosed to implement my design is correct or not.

second, I've got runtime error when I ran the code. malloc(): memory corruption.
I found out this error happens when I create an actor of the function-based actor. I use linux 14.04 to run this program and I run the program with valgrind to find out memory leak but it didn't help.

the line in them main that leads to abort and error:                        monitor_actor monitorActor = self->spawn(data_gathering); 


namespace {

vector< vector< int > > r1;
vector< vector< int > > r2;
vector< vector< int > > r3;

using B_component
= typed_actor<result<void>(check_with_monitor_atom, int, int, int)>;

   B_component::behavior_type data_gathering(B_component::pointer self){
    return {
    [=](check_with_monitor_atom, int intT1, int intT2,int intT3) -> result<void> {
    r1[0] = intT1;
                         r2[0] = intT2;
       r3[0] = intT3;
                      //
    }
    };
    }

   class controller : public event_based_actor {
public:
controller(actor_config& cfg, monitor_actor m)
  : event_based_actor(cfg),
  monitor_(m) {

                                  set_default_handler(skip);
                                  deciding_.assign([=](decide_atom){
                                               send(monitor_ , check_with_monitor_atom_v, 10, 12, 13);
     });
                         }
               
                          behavior_type make_behavior() override {
// start deciding
aout(this) << "start" << endl; 
    send(this, decide_atom_v);
    return deciding_;
}
                };
     
       void caf_main(actor_system& system) {
                        scoped_actor self{system};
                        monitor_actor monitorActor = self->spawn(data_gathering);

                        vector< vector< int > > input1; 
              vector< vector< int > > input2;
        vector< vector< int > > input3;
 
                        readCpsInput(input1, input2, input3);

                        self->spawn<controller>(monitorActor, input1, input2, input3, 21, 23);
       }



I appreciate if you tell me how I can improve my code and get rid of malloc error.
cheers,
Hanieh 

Dominik Charousset

未讀,
2020年7月20日 中午12:22:552020/7/20
收件者:actor-f...@googlegroups.com
Hi Hanieh,

> I defined some vectors in namespace domain which I guess they will be considered global variables and function-based actor will use them.

Is there a particular reason to use global state? Ideally, actors should only access they own state. Adding the three vectors as local state is straightforward:

struct my_state { ... };
B_component::behavior_type data_gathering(B_component::stateful_pointer<my_state> self) { ... }

Unless there's some other reason to use the class-based actors, I'd stick to the stateful actors. The dining philosophers example uses the class-based API mostly because this allows storing the different behaviors as members for switching between them. Do you really need this flexibility?

> second, I've got runtime error when I ran the code. malloc(): memory corruption.
> I found out this error happens when I create an actor of the function-based actor. I use linux 14.04 to run this program and I run the program with valgrind to find out memory leak but it didn't help.

Valgrind probably isn't the best tool for analyzing memory corruptions. During development, I cannot recommend ASAN & friends enough. If the ASAN output isn't enough, I'd run the program in a debugger (LLDB/GDB/...).

Judging from your code: it seems that you corrupt the stack by not returning something from the lambda function inside data_gathering. You promise the compiler a "result<void>", but you aren't actually returning anything. Either drop the return type from the signature or add "return caf::unit;".

Btw, you should see a compiler warning about this. If not, increase the warning level for your compiler. :)

> I appreciate if you tell me how I can improve my code

There are a couple of small things I'd recommend:

- Avoid platform-specific types such as int, because actor messages can cross the wire. I know int is 32-bit on almost all platforms, but "long" for example can have 32 or 64 bits. Always using the fixed-size aliases such as int32_t can prevent subtle bugs when deploying an application to a heterogeneous environment.

- Repeating vector<vector<int>> in so many places makes the code redundant to read. I also gives no additional semantics to the reader. Why store a list inside a list? Is this supposed to represent a table or 2D matrix? It's of course a stylistic issue, but a type alias can go a long way to add extra semantics to the code and make it less repetitive.

- Move message elements whenever possible. For example:

self->spawn<controller>(monitorActor, std::move(input1), std::move(input2), std::move(input3), 21, 23);

Otherwise, you make unnecessary copies of all three vectors (at least judging from your code, the vectors seemingly aren't used afterwards).


Hope that helps.

Dominik
回覆所有人
回覆作者
轉寄
0 則新訊息