Segmentation Fault in aerospike_key_get()


#1
   RtCliErrors RtZonalDao::rtDispZonalCodes(char * p_ZnCodeListName, vector <struct RtDispRgZnCode> & dispRgZnCodeVec)
{
        printf("\n[%s::%d] === Inside rtDispZonalCodes() === \n",__FILE__,__LINE__);

        as_error l_asError;
        as_key l_key ;
        as_record l_rec;

        try{
                if(aerospike_cluster_is_connected(&RtDbConnection::ms_aerospikeIns) == true)
                {
                        printf("\n[%s::%d] === aerospike connection OK ===",__FILE__,__LINE__);
                }
                else{
                        printf("\n[%s::%d] aerospike is not connected",__FILE__,__LINE__);
                        return RT_FAILURE;
                }

                if(p_ZnCodeListName==NULL)
                {
                        printf("\n[%s::%d] Error: Null value of ZnCodeListName \n",__FILE__,__LINE__);
                        return RT_FAILURE;
                }

                if(p_ZnCodeListName!=NULL&&p_ZnCodeListName[0]==0)
                {
                        printf("\n[%s::%d] Error: Null value of ZnCodeListName \n",__FILE__,__LINE__);
                        return RT_FAILURE;
                }

                as_key_init_str(&l_key, "bar", "rg_zn_cd_list_id_name", p_ZnCodeListName);

                printf("\n[%s::%d] Key initialised successfully\n",__FILE__,__LINE__);
                as_record* p_rec=&l_rec;

                if (aerospike_key_exists(&RtDbConnection::ms_aerospikeIns, &l_asError, NULL, &l_key, &p_rec) == AEROSPIKE_ERR_RECORD_NOT_FOUND)
                {
                        as_record_destroy(&l_rec);

                        as_key_destroy(&l_key);

                        printf("\n[ %s::%d ]--> Exception: , RG_ZN_CD_LIST not present in Db\n",__FILE__,__LINE__);

                        return RT_RG_ZN_CD_LST_NOT;
                }

                else
                        printf("\n[%s::%d] Primary Key found\n",__FILE__,__LINE__);
                if (aerospike_key_get(&RtDbConnection::ms_aerospikeIns, &l_asError, NULL, &l_key, &p_rec) != AEROSPIKE_OK)
                {
                        as_record_destroy(&l_rec);

                        as_key_destroy(&l_key);

                        printf("\n[%s::%d] Exception! Error Code: %d, Error Msg: %s\n",__FILE__,__LINE__, l_asError.code, l_asError.message);

                        return RT_FAILURE;

                }


                printf("\n[%s::%d] Fetch success\n",__FILE__,__LINE__);
                as_record_destroy(&l_rec);

                as_key_destroy(&l_key);


                return RT_SUCCESS;

        }//end of try
        catch(...)
        {
                printf("\n[%s::%d] Default Exeption Caught \n",__FILE__,__LINE__);

                as_record_destroy(&l_rec);

                as_key_destroy(&l_key);
                return RT_FAILURE;
        }

}

I’m at my wits’ end here. I’ve been trying to find out the problem in my client code but still unsuccessful. I’m getting weird observations. The above API runs fine the very first time it’s called by the main program, but when I call it for the second time it gives segmentation fault. Given below is a snippet of Valgrind output:

==14471== Conditional jump or move depends on uninitialised value(s)
==14471==    at 0x4A0A965: memcpy (vg_replace_strmem.c:1023)
==14471==    by 0x4E77C4B: as_command_parse_bins (as_command.c:985)
==14471==    by 0x4E7805E: as_command_parse_result (as_command.c:1167)
==14471==    by 0x4E787D2: as_command_execute (as_command.c:492)
==14471==    by 0x4E6DF22: aerospike_key_get (aerospike_key.c:136)
==14471==    by 0x4042D0: RtZonalDao::rtDispZonalCodes(char*, std::vector<RtDispRgZnCode, std::allocator<RtDispRgZnCode> >&) (RtZonalDao.cpp:90)
==14471==    by 0x404679: RtZonalDao::rtAddRgZnCodeToList(RtRgZonalCodes*, char*) (RtZonalDao.cpp:370)
==14471==    by 0x407665: RtZonalDaoTest::rtAdd() (RtZonalDaoTest.cpp:94)
==14471==    by 0x403134: main (RtMain.cpp:194)
==14471==  Uninitialised value was created by a stack allocation
==14471==    at 0x4041A8: RtZonalDao::rtDispZonalCodes(char*, std::vector<RtDispRgZnCode, std::allocator<RtDispRgZnCode> >&) (RtZonalDao.cpp:24)
==14471==
==14471== Use of uninitialised value of size 8
==14471==    at 0x4A0A9AB: memcpy (vg_replace_strmem.c:1023)
==14471==    by 0x4E77C4B: as_command_parse_bins (as_command.c:985)
==14471==    by 0x4E7805E: as_command_parse_result (as_command.c:1167)
==14471==    by 0x4E787D2: as_command_execute (as_command.c:492)
==14471==    by 0x4E6DF22: aerospike_key_get (aerospike_key.c:136)
==14471==    by 0x4042D0: RtZonalDao::rtDispZonalCodes(char*, std::vector<RtDispRgZnCode, std::allocator<RtDispRgZnCode> >&) (RtZonalDao.cpp:90)
==14471==    by 0x404679: RtZonalDao::rtAddRgZnCodeToList(RtRgZonalCodes*, char*) (RtZonalDao.cpp:370)
==14471==    by 0x407665: RtZonalDaoTest::rtAdd() (RtZonalDaoTest.cpp:94)
==14471==    by 0x403134: main (RtMain.cpp:194)
==14471==  Uninitialised value was created by a stack allocation
==14471==    at 0x4041A8: RtZonalDao::rtDispZonalCodes(char*, std::vector<RtDispRgZnCode, std::allocator<RtDispRgZnCode> >&) (RtZonalDao.cpp:24)
==14471==
==14471== Invalid write of size 8
==14471==    at 0x4A0A9AB: memcpy (vg_replace_strmem.c:1023)
==14471==    by 0x4E77C4B: as_command_parse_bins (as_command.c:985)
==14471==    by 0x4E7805E: as_command_parse_result (as_command.c:1167)
==14471==    by 0x4E787D2: as_command_execute (as_command.c:492)
==14471==    by 0x4E6DF22: aerospike_key_get (aerospike_key.c:136)
==14471==    by 0x4042D0: RtZonalDao::rtDispZonalCodes(char*, std::vector<RtDispRgZnCode, std::allocator<RtDispRgZnCode> >&) (RtZonalDao.cpp:90)
==14471==    by 0x404679: RtZonalDao::rtAddRgZnCodeToList(RtRgZonalCodes*, char*) (RtZonalDao.cpp:370)
==14471==    by 0x407665: RtZonalDaoTest::rtAdd() (RtZonalDaoTest.cpp:94)
==14471==    by 0x403134: main (RtMain.cpp:194)
==14471==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14471==
==14471==
==14471== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==14471==  Access not within mapped region at address 0x0
==14471==    at 0x4A0A9AB: memcpy (vg_replace_strmem.c:1023)
==14471==    by 0x4E77C4B: as_command_parse_bins (as_command.c:985)
==14471==    by 0x4E7805E: as_command_parse_result (as_command.c:1167)
==14471==    by 0x4E787D2: as_command_execute (as_command.c:492)
==14471==    by 0x4E6DF22: aerospike_key_get (aerospike_key.c:136)
==14471==    by 0x4042D0: RtZonalDao::rtDispZonalCodes(char*, std::vector<RtDispRgZnCode, std::allocator<RtDispRgZnCode> >&) (RtZonalDao.cpp:90)
==14471==    by 0x404679: RtZonalDao::rtAddRgZnCodeToList(RtRgZonalCodes*, char*) (RtZonalDao.cpp:370)
==14471==    by 0x407665: RtZonalDaoTest::rtAdd() (RtZonalDaoTest.cpp:94)
==14471==    by 0x403134: main (RtMain.cpp:194)
==14471==  If you believe this happened as a result of a stack
==14471==  overflow in your program's main thread (unlikely but
==14471==  possible), you can try to increase the size of the
==14471==  main thread stack using the --main-stacksize= flag.
==14471==  The main thread stack size used in this run was 10485760.
==14471==
==14471== HEAP SUMMARY:
==14471==     in use at exit: 248,960 bytes in 70 blocks
==14471==   total heap usage: 126 allocs, 56 frees, 260,256 bytes allocated

Is there any problem in any part of the code I’ve provided above?


#2

You are passing in a pointer to a uninitialized record. The client code assumes you have already initialized the record and tries to reuse the structure. This will result in corruption.

There are two ways to fix.

  1. Pass in a pointer to a NULL record pointer. The client will allocate the record for you in this case:
as_record* p_rec = NULL;
aerospike_key_get(&RtDbConnection::ms_aerospikeIns, &l_asError, NULL, &l_key, &p_rec)
  1. Pass in a pointer to an initialized record.
as_record rec;
as_record_init(&rec, nbins);  // Use as_record_inita() to place rec bins on stack.
as_record* p_rec = &rec;
aerospike_key_get(&RtDbConnection::ms_aerospikeIns, &l_asError, NULL, &l_key, &p_rec)

#3

Hi Brian! Thanks a lot for your response. I’ve got a query regarding your 2nd example. You passed an as_record * to aerospike_key_get() after you had initialised as_record* with ‘nbins’. Suppose, in my set, there are x bins stored in the database corresponding to l_key(the primary key) where x > nbins. How many(and which) bins will p_rec contain after the execution of aerospike_key_get in this scenario.


#4

If returned bins > nbins, the client will reallocate bins to the proper size. This defeats the purpose of pre-allocating the record, so method #1 is preferred when you don’t have a good idea of the maximum bins that will be returned from the server.


#5

One more thing, if I want to re-use objects like as_record/as_key, then should I first destroy it to release the pre-allocated resources and then reuse it or can I reuse it as many times as I want and then release the resources in the end. for e.g if I init as_key with key 1 first and after using it I want to init it with key 2, then should I destroy as_key first before associating key 2 with it?


#6

Do not destroy as_key if you plan to reuse the exact same key value. If you plan to change the as_key value, then destroy it first and reset the as_key with the new value.

If you plan to re-use as_record, you should not destroy it. Each as_record get() function will automatically destroy the bin values from the previous call, but preserve the bin array itself if the array capacity is sufficient to handle the current record get() returned bins.


#7

Including an example just to be sure. Say, I use an as_record as_rec; in aerospike_key_get() to fetch a record from a set(Set 1). Now, in order to use the same as_record in aerospike_key_put()(for inserting a record in some other set, Set 2, should I straight away init as_rec with the number of bins in Set 2(Set 1 and Set 2 have unequal number of bins) or should I first destroy as_rec and then do the resource allocation?


#8

You should destroy as_rec after aerospike_key_get() and initialize a new as_rec for aerospike_key_put(). The reason is the bin values from aerospike_key_get() need to be destroyed because they are not the same bin values you are using in aerospike_key_put().


#9

This topic was automatically closed 6 days after the last reply. New replies are no longer allowed.