【问题标题】:Segmentation fault on malloc functionmalloc 函数的分段错误
【发布时间】:2016-03-08 17:11:59
【问题描述】:

我有一个脚本通过 SSH (libssh2) 连接到我的 10 台服务器之一。该程序使用fork 作为线程系统。它正在进入服务器,执行命令(如free -m 或检查 CPU 使用情况),然后通过 HTTP REQUEST 将输出发送到另一台服务器。

它工作得很好,但有时它不会将数据发送回 HTTP SERVER。我用puts('DEBUG123 ...') 做了一点调试,看看它在哪里崩溃。我这样做是因为我使用FORK,但我无法看到它在哪里崩溃。下面你会看到代码。

... code from the fork
puts("DEBUG 6");
sprintf(param,"%s%s",param,my_encode(info));
puts("DEBUG 6.5");
getContent(MY_HOST,HOST_IP,param);
puts("DEBUG 7");
... code from the fork

在将数据发送到 HTTP SERVER 之前加密我的数据的 my_encode 函数的代码:

char *my_encode(char* bytes_to_encode)
{
    puts("S-DEBUG 1");
    int in_len = strlen(bytes_to_encode);
    puts("S-DEBUG 1.1");
    char buf[5200];
    char *res = (char *)malloc(3600);
    puts("S-DEBUG 1.2");
    memset(buf,0,1200);
    puts("S-DEBUG 1.3");
    memset(res,0,3600);
    puts("S-DEBUG 2");

    strcpy(buf,base64_encode(bytes_to_encode,in_len));

    for(int i=0;i<strlen(buf);i++)
    {
        strcat(res,switch_encode(buf[i]));
    }
    puts("S-DEBUG 3");
    return res;

}

这是我得到的输出:

Linux -> username password 1.2.3.4 22
DEBUG 2
DEBUG 3
DEBUG 4
DEBUG 5
DEBUG 6
S-DEBUG 1
S-DEBUG 1.1
S-DEBUG 1.2
S-DEBUG 1.3
S-DEBUG 2
S-DEBUG 3
DEBUG 6.5
DEBUG 7
DEBUG 1
-- SUCCESSFUL SEND

Linux -> username password 1.2.3.4 22
DEBUG 2
DEBUG 3
DEBUG 4
DEBUG 5
DEBUG 6
S-DEBUG 1
S-DEBUG 1.1
S-DEBUG 1.2
S-DEBUG 1.3
S-DEBUG 2
S-DEBUG 3
DEBUG 6.5
DEBUG 7
DEBUG 1
-- SUCCESSFUL SEND

Linux -> username password 1.2.3.4 22
DEBUG 2
DEBUG 3
DEBUG 4
DEBUG 5
DEBUG 6
S-DEBUG 1
S-DEBUG 1.1
S-DEBUG 1.2
S-DEBUG 1.3
S-DEBUG 2
S-DEBUG 3
DEBUG 6.5
DEBUG 7
DEBUG 1
-- SUCCESSFUL SEND

Linux -> username password 1.2.3.4 22
DEBUG 2
DEBUG 3
DEBUG 4
DEBUG 5
DEBUG 6
S-DEBUG 1
S-DEBUG 1.1 <--- HERE IT IS CRASHING
DEBUG 1
-- ERROR ON SEND

Linux -> username password 1.2.3.4 22
DEBUG 2
DEBUG 3
DEBUG 4
DEBUG 5
DEBUG 6
S-DEBUG 1
S-DEBUG 1.1
S-DEBUG 1.2
S-DEBUG 1.3
S-DEBUG 2
S-DEBUG 3
DEBUG 6.5
DEBUG 7
-- SUCCESSFUL SEND

Linux -> username password 1.2.3.4 22
DEBUG 2
DEBUG 3
DEBUG 4
DEBUG 5
DEBUG 6
S-DEBUG 1
S-DEBUG 1.1 <--- HERE IT IS CRASHING
DEBUG 1
-- ERROR ON SEND

所以据我了解,这里的malloc 功能崩溃了:

char *res = (char *)malloc(3600);

这是我发送的基本信息:

username:password:1.2.3.4:22:Linux:Intel(R) Core(TM)2 Duo CPU E8200 @ 2.77GHz:242 238 3 0 15 64:no_server_load]

有时它会崩溃。

我还更改了char *res = (char *)malloc(3600); 行,原来是char *res = (char *)malloc(1200);。我认为我没有足够的内存空间。

  1. 问题出在哪里?
  2. 是否需要重写my_encode 函数使其不再崩溃?如果有,怎么做??

谢谢。

【问题讨论】:

  • 你能得到一个核心转储吗?没有它我们只能猜测。
  • 您的for 循环中带有strcat(res,switch_encode(buf[i])); 看起来非常 错误。我怀疑你正在破坏你的堆,这就是 malloc 随后失败的原因。
  • @YSC 它是 C++,尽管它看起来像 C ...我的意思是我使用 g++ 编译它,我该如何进行核心转储?请记住,这是在分叉之后发生的,天知道发生了什么,我看不到它......
  • 你确定你在释放char *res...如果你使用c++你应该使用
  • @PaulR 请解释一下,我不太明白,但错误在char *res = (char *)malloc(3600); 行,最后一个putsS-DEBUG 1.1,达不到S-DEBUG 1.2,明白吗?

标签: c++ pointers


【解决方案1】:

你必须这样做(释放你的缓冲区):

#include <string>
void my_encode(char* bytes_to_encode, std::string& encoded) {
    puts("S-DEBUG 1");
    int in_len = strlen(bytes_to_encode);
    puts("S-DEBUG 1.1");
    char buf[5200];
    char *res = (char *)malloc(3600);
    puts("S-DEBUG 1.2");
    memset(buf,0,1200);
    puts("S-DEBUG 1.3");
    memset(res,0,3600);
    puts("S-DEBUG 2");

    strcpy(buf,base64_encode(bytes_to_encode,in_len));

    for(int i=0;i<strlen(buf);i++)
    {
        strcat(res,switch_encode(buf[i]));
    }
    puts("S-DEBUG 3");

    encoded = res;
    free(res);
}

void main() {
    char *s = new char[32];
    strcpy(s, "hello");
    std::string str;
    my_encode (s, str);
    const char* result = str.c_str();
}

【讨论】:

  • 谢谢你的帮助,真的需要std::string&amp; encoded 吗?我不能活下去char *my_encode(char* bytes_to_encode) 吗?问题是我很清楚我应该使用string 而不是char*char[100] ...但我不想重写3000行到处都使用char* ...
  • 是的,这是最安全的方式...但是还有其他可能性,例如返回字符串(但每次都会复制字符串)
  • // ssh2connect.cpp:621: 错误:数组必须用大括号括起来的初始化程序初始化 ERROR WITH char info2[3000] = ... // ssh2connect.cpp:621: 错误:从 'const char* 无效转换' 到 'char*' 错误,char* info2 = ... 代码:pastebin.com/GTfbpXq9
  • 我已经更新了答案,现在应该可以正常运行了。顺便说一句,如果您需要结果是 char* 而不是 const char*,您将需要再次使用 strcpy
  • main的前两行应该去掉,你可以直接使用"hello"作为参数(函数应该接受char const *
【解决方案2】:

sprintf(param,"%s%s",param,my_encode(info)); 是一个错误。 sprintf 的输入和输出不能重叠,这会导致未定义的行为。

您的意思可能是strcat(param, my_encode(info));,尽管最好包含缓冲区大小检查。

您的代码没有包含任何防止缓冲区溢出的方法。可能会发生溢出,但你不知道在哪里。这可能会或可能不会导致您的问题,您无法判断。即使没有,那么更改输入可能会导致一个。

这是一种糟糕的编码方式,尝试调试它会很困难。我的建议是重写所有这些代码,以包括对缓冲区大小的严格检查,并确保您永远不会读取或写入超出缓冲区的末尾。在 C++ 中,最简单的方法是使用可调整大小的容器。

【讨论】:

  • 我同意你的观点,这将是重写程序的正确方法,但我不想重写 5000 行代码,我只想解决这个问题并继续进行其他项目。 ..所以您的想法是将sprintf(param,"%s%s",param,my_encode(info)); 更改为strcat(param, my_encode(info));?我必须告诉你,相信我,错误来自my_encode函数,我已经测试并重新测试了它......
  • @Damian 这是一个错误,可能有也可能没有其他错误
  • 没有人可以仅根据您发布的代码判断您是否导致缓冲区溢出,但根据您发布的内容,这可能是一个问题。
【解决方案3】:

如果您使用C++ - 使用std::string 来管理内存并避免分配/释放问题。

//get base64.cpp and base64.h 
//from here http://www.adp-gmbh.ch/cpp/common/base64.html
#include <base64.h>

std::string my_encode(const std::string& bytes_to_encode)
{
    puts("S-DEBUG 1");
    std::string output = base64_encode(bytes_to_encode.c_str(),bytes_to_encode.length());
    puts("S-DEBUG 2");
    return output;
}

【讨论】:

    猜你喜欢
    • 2019-04-23
    • 1970-01-01
    • 2014-03-29
    • 2015-01-29
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    相关资源
    最近更新 更多