[英]string copy into malloc'd char array fails with segmentation fault
我正在用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()
並且還將字符從源一個一地復制到dest數組。 但是我也看到了失敗。
我猜create_dynamic_string
和retrieve_client_id
位於不同的編譯單元中,並且當后者編譯時,您沒有可見的正確原型。
該地址0xffffffffcc0008c0
看起來像是一個合理的堆地址0xcc0008c0
帶有附加的位。
添加此行:
extern char *create_dynamic_string(int);
正上方的定義retrieve_client_id
。
如果可以解決該問題(應解決),則將create_dynamic_string
原型添加到適當的頭文件中,並將其#include
到定義retrieve_client_id
的源中。
我不明白為什么它沒有給出編譯錯誤
在C中,未聲明的函數假定具有以下原型:
int undeclared(...);
因此,以下任何通話均不會被拒絕:
int x = undeclared();
int y = undeclared(1);
char *z = undeclared(1, 2, 3);
您可以要求 GCC警告您有關缺少特定-Wmissing-prototypes
,但是最佳實踐是使用-Wall
和-Werror
進行編譯。 后者不會讓您忽略警告並迫使您對其進行修復。
也建議添加-Wextra
,盡管有時它確實會給出假陽性警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.