【问题标题】:Segment fault. Address 0x0 is not stack'd, malloc'd or (recently) free'd段故障。地址 0x0 没有被堆栈、malloc 或(最近)释放
【发布时间】:2014-10-05 18:57:13
【问题描述】:

我对 C++ 很陌生,但我必须解决这个问题。如果您能帮我做,我们将不胜感激。

这是一种每天运行一次的 cron 程序,它一直运行到今天。但它向我显示了一个段错误。它从 mysql 获取用户信息并按城市进行匹配并插入到 mysql 上的表中。所以我运行 valgrind 以获取更多信息,如下所示。

==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== 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  

消息的另一部分告诉我下面的源代码需要修改

    //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);
    }

任何理解这一点的人。请给我简单的指导?

非常感谢您

【问题讨论】:

  • 没有产生该错误的代码的错误只是故事的一半。
  • 疯狂猜测。你会这样做吗:std::string s = 0;
  • main.cpp中哪一行是759?
  • @jrok insertMatchByCity(conn,city);是第 759 行。
  • 我怀疑这个:row[0] 可以包含一个空指针,调用我上面的“疯狂猜测”错误。

标签: c++ gcc segmentation-fault malloc


【解决方案1】:

要猜测的代码非常少,但是,这是我的想法:

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

如果您通过引用将 city 发送到 insertMatchByCity(可能是另一个线程),并且该线程仍未处理其数据,即它仍然持有对 city 的引用。假设线程被操作系统抢占。 现在,您的迭代(while 循环)将继续,并且作为局部范围变量的 city 将被销毁。 所以,现在当该线程尝试取消引用城市时,它会导致崩溃!

应用我的取证分析:)

【讨论】:

  • 感谢您的建议。但直到昨晚它都完美无缺。您认为系统上的某些更改可能会影响运行吗?
  • 这些被称为竞争条件,可以随时出现。在惨遭崩溃之前,我已经看到系统运行了几年。我有预感,我指定的根本原因是罪魁祸首。在这种情况下,更改 insertMatchByCity(conn,city);接受城市作为价值,而不是参考
【解决方案2】:

我认为这可能是您的问题:

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

根据MySQL Docs,您的row[0] 可以包含null 指针。这意味着当您将其推回字符串向量时,std::string 将使用空指针进行初始化。合法,但致命错误。

可以试试这样的吗?

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

或者这个:

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

【讨论】:

  • 非常感谢您的建议,但恐怕这两个代码都不起作用。
  • 尝试添加一个 fprintf(stderr, "row[0]=%p\n", row[0]);到循环的开头——这样如果你在崩溃前看到它打印出 row[0]=0,你就知道空指针是你的问题。
  • @Brianc 你能指出哪一行出现错误吗?
  • @JeremyFriesner 我添加了代码,它显示 row[0]=0xa18b48 row[0]=0xa18b78 row[0]=0xa18ba8 row[0]=0xa18bd8 row[0]=0xa18c08 row[0 ]=0xa18c38 行[0]=0xa18c68 行[0]=0xa18c98 行[0]=0xa18cc8 行[0]=0xa18d00 行[0]=0xa18d30 行[0]=0xa18d60 行[0]=0xa18d90
  • @Brianc 我的意思是原始代码中的哪一行。如果我们知道是哪条线路触发了失败,这将有助于推断原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 2020-04-07
  • 2017-09-13
  • 2018-10-12
  • 1970-01-01
  • 2019-08-21
  • 1970-01-01
相关资源
最近更新 更多