函数调用时的分段错误

时间:2018-04-10 11:39:59

标签: c c99

我有一个struct Chat

struct Chat
{
    int m_FD;
    int m_BindPort;
    char m_NameLength;
    char* m_Name;
    char m_PeerCount;
    char** m_PeerList;

} typedef Chat_t;

我正在使用此功能初始化它:

int chat_init(Chat_t* this, unsigned int nameLen, char* name, unsigned short int bindPort, unsigned int peerCount, char** peerList)
{
    this->m_NameLength = nameLen;
    this->m_Name = malloc(sizeof(char) * (nameLen+1));
    strcpy(this->m_Name, name);
    this->m_BindPort = bindPort;
    this->m_PeerCount = peerCount;
    this->m_PeerList = malloc(sizeof(char*) * peerCount);
    for(int i=0; i<peerCount; i++)
    {
        this->m_PeerList[i] = malloc(sizeof(char) * 16); // enough for xxx.xxx.xxx.xxx\0
        strcpy(this->m_PeerList[i], peerList[i]);
    }

    //Socket initialization for TCP connection...
    //Commenting this out doesn't change anything so i'm hiding it for simplification

    return 0;

}

之后我正在调用第二个函数

int chat_communicate(Chat_t* this)
{
    printf("2\n");
    fflush(stdout);

    //Some stuff that doesn't matter because it isn't even called

    return retVar;
}
像这样的

void main(void)
{
    char* peerList[1];
    char username[USERNAME_MAX_LEN];
    int initRet;
    int loopRet;
    Chat_t chat;

    peerList[0] = "192.168.2.2";

    memset(username, 0, USERNAME_MAX_LEN);

    printf("Please enter your user name: ");
    scanf("%s", username);

    username[USERNAME_MAX_LEN-1] = 0;

    initRet = chat_init(&chat, strlen(username), username, 1234, 1, peerList);

    printf("File Descriptor: %d\n", chat.m_FD);
    printf("Binding Port: %d\n", chat.m_BindPort);
    printf("Name Length: %d\n", chat.m_NameLength);
    printf("Name: %s\n", chat.m_Name);
    printf("Peer Count: %d\n", chat.m_PeerCount);
    for(int i=0; i< chat.m_PeerCount; i++)
    {
      printf("Peer[%d]: %s\n", i, chat.m_PeerList[i]);
    }

    printf("1");
    ret = chat_communicate(&chat);

    //Even more Stuff that isn't even called

}

我的程序输出以下内容

File Descriptor: 3
Binding Port: 1234
Name Length: 4
Name: User
Peer Count: 1
Peer[0]: 192.168.2.2
1
Segmentation Fault

它编译时没有错误甚至是警告。

你也可以假设每个字符串都是空的 - 终止我用评论替换的东西并不复杂但只是显示太多。

结构中的每个值都在前面打印printf,但是当每次引用传递这个结构时,应用程序崩溃。

我想知道的是为什么我会遇到此分段错误。因为它在调用函数时出现了,我认为它是某种布局问题,但我找不到类似的东西。

加成: 因为有些人无法相信我隐藏在“某些东西”后面的代码评论没有改变任何我想在此处声明的内容再次。此代码仅包含tcp套接字通信,仅执行读取操作。我也可以在没有这个代码的情况下重现上面提到的错误,所以请不要陷入困境。部件根本不会影响观察对象。

4 个答案:

答案 0 :(得分:3)

在其他潜在问题中,

<!DOCTYPE html>
<html>
<body>
<ul id="list">
</ul>
<p id="demo" onClick="show()">Click ME</p>
</body>
</html>

显然是错误的。

this->m_PeerList = malloc(sizeof(char)*peerCount); m_PeerList,但您只分配char **个字节,只有当peerCount指针是您系统上的一个字节时才有效可能的。

将其替换为

char *

请注意this->m_PeerList = malloc(peerCount * sizeof( *( this->m_peerList ) ) ); 始终是一个 - 按定义。

答案 1 :(得分:2)

现在您已经发布了几乎完整的代码,我能够发现彼此相邻的两个问题:

    int chat_init(Chat_t* this, unsigned int nameLen, char* name, unsigned short int bindPort, unsigned int peerCount, char** peerList)
    {
      this->m_NameLength = nameLen;

      this->m_Name = malloc(sizeof(char) * (nameLen + 1)); // correct
  //< this->m_Name = malloc(sizeof(char) * nameLen);       // wrong

      strcpy(this->m_Name, name);                          // correct
  //< memcpy(this->m_Name, name, nameLen);                 // wrong
      ...

//<开头的行是您的原始代码:

在这里你没有分配足够的空间,你需要考虑NUL终结器:

this->m_Name = malloc(sizeof(char) * nameLen);

在这里你不复制NUL终止符:

memcpy(this->m_Name, name, nameLen);

你真的需要知道字符串在C中是如何工作的。

答案 2 :(得分:1)

您没有为this->m_Name分配足够的内存。如果您希望它存储名称的以null结尾的字符串,那么它应该不止于此。

那,或者我们需要有关peerList的更多信息。

答案 3 :(得分:1)

为什么不自己调试呢。如果使用GCC,请使用选项-g -O0编译代码。然后使用gdb

运行它
gdb ./a.out
...
(gdb) r

如果崩溃了:

(gdb) bt

这将准确地说明它崩溃的地方。

更新:其他用户可能会发现您的代码存在潜在问题。但是,与内存分配相关的问题不会在调用函数chat_communicate时使应用程序崩溃。这种行为可能有不同的原因,从堆栈溢出到不正确的编译。没有看到整个代码,很难说。最好的建议是考虑其他用户的评论意见并自行调试。