c - 将字符串复制到 malloc 的 char 数组中失败并出现段错误

标签 c gdb malloc client-server

我正在练习用 C 编写的客户端-服务器应用程序。在该应用程序中,客户端首先向服务器注册并获得 client_id 作为返回。下一次,客户端将消息发送到服务器,并在消息前加上 client_id。以下代码片段来自服务器,服务器收到消息后,从消息中获取client_id,这是一个3字符长的字符串,起始地址为1,结束地址为4大批。例如。在消息 "1001CLIENT:001:MESSAGE:01" 中,位置 0 处的 '1' 用于某种目的,"001"是 client_id"CLIENT :001:MESSAGE:01" 是来自客户端的消息。

char *create_dynamic_string(int str_size)
{
        char *dyn_string = malloc(str_size*sizeof(char));
        if(!dyn_string)
        {
                printf("Dynamic string could not be created");
                return NULL;
        }
        dyn_string[0] = '\0';
        return dyn_string;
}

void free_dynamic_string(char *dyn_string)
{
        free(dyn_string);
}

//char *message is dynamically allocated char array.
char *retrieve_client_id(char *message)
{
        char *client_id;
        int i;
        client_id = create_dynamic_string(CLIENT_ID_SIZE + 1);

        if(!client_id)
        {
                printf("Client_id is NULL");
                return NULL;
        }
        //for(i = 1; i < (CLIENT_ID_SIZE + 1); i++)
        //      client_id[i-1] = message[i];

        //strncpy(client_id, message + 1, CLIENT_ID_SIZE);

        memcpy(client_id, message + 1, CLIENT_ID_SIZE);

        client_id[CLIENT_ID_SIZE] = '\0';
        printf("client_id retrieved=%s", client_id);
        return client_id;
}

服务器接受来自客户端的连接并在不同的线程中处理消息。多线程和消息处理的工作已成功测试。下面的代码编译成功并且大部分时间都有效。但有时它会在 retrieve_client_id() 中的 memcpy() 处出现段错误。我无法弄清楚为什么它会以这种方式失败。

我使用 gdb 来获取更多信息。如下所示。

Program terminated with signal 11, Segmentation fault.
#0  0x00000000004017ef in retrieve_client_id (message=0x1b904f40 "1000CLIENT:000:MESSAGE:02") at src/server.c:46
46              memcpy(client_id, message + 1, CLIENT_ID_SIZE);
(gdb) print message
$1 = 0x1b904f40 "1000CLIENT:000:MESSAGE:02"
(gdb) print message+1
$2 = 0x1b904f41 "000CLIENT:000:MESSAGE:02"
(gdb) print CLIENT_ID_SIZE
$3 = 3
(gdb) print client_id
$4 = 0xffffffffcc0008c0 <Address 0xffffffffcc0008c0 out of bounds>
(gdb)               

需要帮助来理解当应用程序失败时究竟会发生什么。我已验证 malloc 成功并且 client_id 不为 NULL。如您所见的注释代码,我还尝试使用 strcpy() 并将字符从源数组一一复制到目标数组。但我也看到了失败。

最佳答案

我猜测 create_dynamic_stringretrieve_client_id 在不同的编译单元中,并且在编译后者时您没有正确的前者可见原型(prototype)。

这个地址 0xffffffffcc0008c0 看起来像一个合理的堆地址 0xcc0008c0 添加了额外的位。

添加这一行:

extern char *create_dynamic_string(int);

就在 retrieve_client_id 的定义之上。

如果这解决了问题(它应该),那么将 create_dynamic_string 的原型(prototype)添加到适当的头文件中,并将其 #include 添加到定义 retrieve_client_id 的源代码中

I did not understand why it did not give compilation error

在 C 中,假定未声明的函数具有以下原型(prototype):

int undeclared(...);

因此,以下任何调用都不会被拒绝:

int x = undeclared();
int y = undeclared(1);
char *z = undeclared(1, 2, 3);

您可以要求 GCC 警告您缺少原型(prototype),特别是-Wmissing-prototypes,但最佳做法是使用-Wall 进行编译> 和 -Werror。后者不会让您忽略警告并强制您修复它们。

还建议添加 -Wextra,尽管它有时会给出误报警告。

关于c - 将字符串复制到 malloc 的 char 数组中失败并出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31922115/

相关文章:

c++ - GDB分步调试两个线程

rust - 如何在异步函数中设置断点?

gdb 在 macOS 上不读取核心转储

c - 重新分配() : realloc invalid next size and malloc(): malloc memory corruption fast

c - C中的malloc内存分配方案

c++ - 为什么 select 调用不会阻塞在 unix 域套接字上?

c - 查找哪条指令在 Cortex M3 上导致了陷阱

c - 使用 size_t 变量时循环没有结束

c - 在这种情况下 malloc 和 realloc 会发生什么

c - 简单的 C 程序,使用 dev c++ 执行时出错