数组中的段错误和 C 中的指针
Segmentation Fault in Array and Pointer in C
我在用数组和指针编写程序时遇到了这个分段错误。任何人都可以解释为什么我在此代码中遇到此分段错误。
我的代码:
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
int main(void)
{
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
char CPID[50] = "98f5b52a59aa4503999894c10bc33dca" ;
char Uni_ID[10] = "Demo123" ;
char *postData;
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "https://avnetagent.iotconnect.io/api/2.0/agent/sync");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
//postData = "{\"cpId\":\""+CPID+"\",\"uniqueId\":\""+Uni_ID+"\",\"option\":{\"attribute\":false,\"setting\":false,\"protocol\":false,\"device\":false,\"sdkConfig\":false,\"rule\":false}}";
postData = "{\"cpId\":\"";
strcat(postData,CPID);
strcat(postData,"\",\"uniqueId\":\"");
strcat(postData,Uni_ID);
strcat(postData,"\",\"option\":{\"attribute\":false,\"setting\":false,\"protocol\":false,\"device\":false,\"sdkConfig\":false,\"rule\":false}}");
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
问题出在
strcat(postData,CPID);
postData
指向的内存既不可修改也没有足够的 space 来保存连接的字符串。
您需要
- 创建
postData
一个维度足以容纳连接字符串的数组。
- 使用分配器函数(
malloc()
和系列)分配足够的内存并将该指针存储在 postData
。
添加,来自strcat()
man page
char *strcat(char *dest, const char *src);
The strcat()
function appends the src
string to the dest
string, overwriting the terminating null byte ('[=20=]'
) at the end of dest
, and then adds a terminating null byte. The strings may not overlap, and the dest
string must have enough space for the result.If dest
is not large enough, program behavior is unpredictable; [...]
您正在 1) 写入不允许您修改的内存和 2) 写入不属于您的内存。
这里
postData = "{\"cpId\":\"";
您将指针 postData
设置为指向字符串文字,即不允许修改的常量字符串。然而,你
strcat(postData,CPID);
这会将字符串 CPID
附加到字符串文字。换句话说 - 它将通过覆盖其字符串终止字符来修改字符串文字,并且进一步它将 CPID
的部分复制到字符串文字之后的内存中。两种操作均无效。
你需要的是让postData
指向可以修改的内存。
修复 1:
char *postData; ---> char postData[8192];
postData = "{\"cpId\":\""; ---> strcpy(postData, "{\"cpId\":\"");
修复 2:
char *postData; ---> char *postData = malloc(8192);
assert(postData != NULL);
postData = "{\"cpId\":\""; ---> strcpy(postData, "{\"cpId\":\"");
return 0; ---> free(postData);
return 0;
这两个修复的缺点是固定的内存大小(即 8192 个字符)。对于您要 post 的数据,这是否总是足够的内存?
如果你知道上限,你可以设置一个固定大小(就像我一样)。
如果您不知道上限,则必须更改代码以便可以在 运行 时增加分配的内存,例如使用 realloc
(仅适用于“Fix 2”)。
请注意,使用具有大量内存的“修复 1”,例如char postData[8192000];
在大多数系统上都是一个问题,因为它们对具有自动存储持续时间的变量有大小限制。
所以总结:
如果您知道数据的大小上限 post 并且 限制是合理的小,您可以使用简单的 Fix 1。
否则我会推荐修复 2。
我在用数组和指针编写程序时遇到了这个分段错误。任何人都可以解释为什么我在此代码中遇到此分段错误。
我的代码:
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
int main(void)
{
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
char CPID[50] = "98f5b52a59aa4503999894c10bc33dca" ;
char Uni_ID[10] = "Demo123" ;
char *postData;
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "https://avnetagent.iotconnect.io/api/2.0/agent/sync");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
//postData = "{\"cpId\":\""+CPID+"\",\"uniqueId\":\""+Uni_ID+"\",\"option\":{\"attribute\":false,\"setting\":false,\"protocol\":false,\"device\":false,\"sdkConfig\":false,\"rule\":false}}";
postData = "{\"cpId\":\"";
strcat(postData,CPID);
strcat(postData,"\",\"uniqueId\":\"");
strcat(postData,Uni_ID);
strcat(postData,"\",\"option\":{\"attribute\":false,\"setting\":false,\"protocol\":false,\"device\":false,\"sdkConfig\":false,\"rule\":false}}");
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
问题出在
strcat(postData,CPID);
postData
指向的内存既不可修改也没有足够的 space 来保存连接的字符串。
您需要
- 创建
postData
一个维度足以容纳连接字符串的数组。 - 使用分配器函数(
malloc()
和系列)分配足够的内存并将该指针存储在postData
。
添加,来自strcat()
man page
char *strcat(char *dest, const char *src);
The
strcat()
function appends thesrc
string to thedest
string, overwriting the terminating null byte ('[=20=]'
) at the end ofdest
, and then adds a terminating null byte. The strings may not overlap, and thedest
string must have enough space for the result.Ifdest
is not large enough, program behavior is unpredictable; [...]
您正在 1) 写入不允许您修改的内存和 2) 写入不属于您的内存。
这里
postData = "{\"cpId\":\"";
您将指针 postData
设置为指向字符串文字,即不允许修改的常量字符串。然而,你
strcat(postData,CPID);
这会将字符串 CPID
附加到字符串文字。换句话说 - 它将通过覆盖其字符串终止字符来修改字符串文字,并且进一步它将 CPID
的部分复制到字符串文字之后的内存中。两种操作均无效。
你需要的是让postData
指向可以修改的内存。
修复 1:
char *postData; ---> char postData[8192];
postData = "{\"cpId\":\""; ---> strcpy(postData, "{\"cpId\":\"");
修复 2:
char *postData; ---> char *postData = malloc(8192);
assert(postData != NULL);
postData = "{\"cpId\":\""; ---> strcpy(postData, "{\"cpId\":\"");
return 0; ---> free(postData);
return 0;
这两个修复的缺点是固定的内存大小(即 8192 个字符)。对于您要 post 的数据,这是否总是足够的内存?
如果你知道上限,你可以设置一个固定大小(就像我一样)。
如果您不知道上限,则必须更改代码以便可以在 运行 时增加分配的内存,例如使用 realloc
(仅适用于“Fix 2”)。
请注意,使用具有大量内存的“修复 1”,例如char postData[8192000];
在大多数系统上都是一个问题,因为它们对具有自动存储持续时间的变量有大小限制。
所以总结:
如果您知道数据的大小上限 post 并且 限制是合理的小,您可以使用简单的 Fix 1。
否则我会推荐修复 2。