Brianc
Brianc

Reputation: 27

Segment fault. Address 0x0 is not stack'd, malloc'd or (recently) free'd

I am pretty new to C++ but I kinda got to solve this problem. It will be really really appreciated if you can help me to do.

It is a kind of cron program which run once a day and it worked well until today. But it showed me a segment fault. It gets user information from mysql and make some match by city and insert into a table on the mysql. so I ran valgrind to get some more information as below.

==11897== Invalid read of size 1  
==11897==    at 0x4C28F52: strlen (mc_replace_strmem.c:403)  
==11897==    by 0x5BF614B: std::string::operator=(char const*) (in /usr/lib64/libstdc++.so.6.0.13)  
==11897==    by 0x4039E7: insertMatchByCity(st_mysql*, std::string) (main.cpp:156)  
==11897==    by 0x407DB5: main (main.cpp:759)  
==11897==  Address 0x0 is not stack'd, malloc'd or (recently) free'd  

AND this as well

==11897== LEAK SUMMARY:  
==11897==    definitely lost: 0 bytes in 0 blocks  
==11897==    indirectly lost: 0 bytes in 0 blocks  
==11897==      possibly lost: 321,326 bytes in 9,167 blocks  
==11897==    still reachable: 609,929 bytes in 1,886 blocks  
==11897==         suppressed: 0 bytes in 0 blocks  
==11897== Reachable blocks (those to which a pointer was found) are not shown.  
==11897== To see them, rerun with: --leak-check=full --show-reachable=yes  
==11897==   
==11897== ERROR SUMMARY: 9 errors from 9 contexts (suppressed: 6 from 6)  
==11897==   
==11897== 1 errors in context 1 of 9:  
==11897== Invalid read of size 1  
==11897==    at 0x4C28F52: strlen (mc_replace_strmem.c:403)  
==11897==    by 0x5BF614B: std::string::operator=(char const*) (in /usr/lib64/libstdc++.so.6.0.13)  
==11897==    by 0x4039E7: insertMatchByCity(st_mysql*, std::string) (main.cpp:156)  
==11897==    by 0x407DB5: main (main.cpp:759)  
==11897==  Address 0x0 is not stack'd, malloc'd or (recently) free'd  
==11897==   
--11897--   
--11897-- used_suppression:      4 U1004-ARM-_dl_relocate_object  
--11897-- used_suppression:      2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a  
==11897==   
==11897== ERROR SUMMARY: 9 errors from 9 contexts (suppressed: 6 from 6)  
Segmentation fault  

and the other part of the msg showed me that source code below need revised

    //get open city list
    vector<string> cityList;

  sql = "SELECT distinct cityname FROM citylist WHERE open=1";

    if(mysql_query(conn,sql.c_str())){
        fprintf(stderr,"%s\n",mysql_error(conn));
        exit(1);
    }

    res = mysql_store_result(conn);

    while((row = mysql_fetch_row(res))!=NULL){
        cityList.push_back(row[0]);
    }
    mysql_free_result(res);

    //match according city
    while(cityList.size()>0){
        string city = cityList[cityList.size()-1];
        insertMatchByCity(conn,city);
        cityList.erase(cityList.end()-1);
    }

Anyone who understand this well. give me easy direction please?

Thanks you very much in advance

Upvotes: 1

Views: 1883

Answers (2)

sanjayk79
sanjayk79

Reputation: 562

There's very small amount of code to guess, but, here's what I think:

while(cityList.size()>0){
    string city = cityList[cityList.size()-1];
    insertMatchByCity(conn,city);
    cityList.erase(cityList.end()-1);
}

If you are sending out city to insertMatchByCity by reference (may be to another thread), and that thread has still not processed its data i.e. it is still holding reference to city. Lets say that thread gets preempted by OS. Now, your iteration (while loop) will continue and city which is a local scoped variable will be destroyed. So, now when that thread tries to de-reference city, it results in a crash!

Applying my forensic analysis :)

Upvotes: 1

Galik
Galik

Reputation: 48635

I think this may be your problem:

while((row = mysql_fetch_row(res))!=NULL){
    cityList.push_back(row[0]);
}

According to the MySQL Docs your row[0] can contain a null pointer. That means when you push it back onto your vector of strings a std::string is initialized with a null pointer. Legal, but a fatal error.

Maybe try something like this?

while((row = mysql_fetch_row(res))!=NULL){
    if(row[0])
        cityList.push_back(row[0]); // if you don't want blank items
}

Or this:

while((row = mysql_fetch_row(res))!=NULL){
    cityList.push_back(row[0] ? row[0] : ""); // if blank items are ok
}

Upvotes: 0

Related Questions