أخطاء Valgrind متعددة: القفزة الشرطية أو التحرك تعتمد على القيمة (القيمة) غير المخصصة
-
30-09-2019 - |
سؤال
أنا أقوم بتشغيل Valgrind وأتلقى الخطأ التالي (هذا ليس هو الوحيد):
==21743== Conditional jump or move depends on uninitialised value(s)
==21743== at 0x4A06509: index (mc_replace_strmem.c:164)
==21743== by 0x33B7CBB3CD: gaih_inet (in /lib64/libc-2.5.so)
==21743== by 0x33B7CBD629: getaddrinfo (in /lib64/libc-2.5.so)
==21743== by 0x401A5F: tunnelURL (proxy.c:336)
==21743== by 0x40142A: client_thread (proxy.c:194)
==21743== by 0x33B8806616: start_thread (in /lib64/libpthread-2.5.so)
==21743== by 0x33B7CD3C2C: clone (in /lib64/libc-2.5.so)
لي tunnelURL()
الدالة تبدو مثل هذا (رمز C):
char * tunnelURL(char *url) {
char * a = strstr(url, "//");
a += 2;
char * path = strstr(a, "/");
char host[256];
strncpy (host, a, strlen(a)-strlen(path));
/*
* The following is courtesy of Beej's Guide
*/
int status;
int proxySocketFD;
struct addrinfo hints;
struct addrinfo *servinfo; // will point to the results
memset(&hints, 0, sizeof(hints)); // make sure the struct is empty
hints.ai_family = AF_INET; // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
if ((status = getaddrinfo(host, "80", &hints, &servinfo)) != 0) {
perror("getaddrinfo() fail");
exit(1);
}
// create socket
if ((proxySocketFD = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
perror("proxy socket() fail");
exit(1);
}
// connect
if (connect(proxySocketFD, servinfo->ai_addr, servinfo->ai_addrlen) != 0) {
printf("connect() fail");
exit(1);
}
// construct request
char request[strlen(path) + strlen(host) + 26];
sprintf(request, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", path, host);
printf("%s", request);
// send request
send(proxySocketFD, request, strlen(request), 0);
// receive response
int i = 0;
int amntRecvd = 0;
char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
i += amntRecvd;
realloc(pageContentBuffer, i * 4096 * sizeof(char));
}
// close proxy socket
close(proxySocketFD);
// deallocate memory
freeaddrinfo(servinfo);
return pageContentBuffer;
}
السطر 336 يتوافق مع if
بيان مع getaddrinfo()
استدعاء وظيفة. لست متأكدًا حقًا مما لم أكن فيه. السلسلة التي أعمرها "يجب أن" يجب تعيينها بالفعل. أنا أقوم بطبعها على ما يرام. أحصل أيضًا على خطأ آخر يتوافق مع نفس سطر التعليمات البرمجية:
==21743== Use of uninitialised value of size 8
==21743== at 0x33B7D05816: __nscd_cache_search (in /lib64/libc-2.5.so)
==21743== by 0x33B7D0438B: nscd_gethst_r (in /lib64/libc-2.5.so)
==21743== by 0x33B7D04B26: __nscd_gethostbyname2_r (in /lib64/libc-2.5.so)
==21743== by 0x33B7CE9F5E: gethostbyname2_r@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==21743== by 0x33B7CBC522: gaih_inet (in /lib64/libc-2.5.so)
==21743== by 0x33B7CBD629: getaddrinfo (in /lib64/libc-2.5.so)
==21743== by 0x401A5F: tunnelURL (proxy.c:336)
==21743== by 0x40142A: client_thread (proxy.c:194)
==21743== by 0x33B8806616: start_thread (in /lib64/libpthread-2.5.so)
==21743== by 0x33B7CD3C2C: clone (in /lib64/libc-2.5.so)
أي أفكار حول ما يمكن أن يكون هذا؟
المحلول
أنت لا تستخدم realloc()
بشكل صحيح. realloc()
قد تحريك الكتلة المخصصة ، ويعيد العنوان الجديد للكتلة - لذلك تحتاج إلى تعيين قيمة الإرجاع هذه pageContentBuffer
(IFF ليس كذلك NULL
).
نصائح أخرى
// receive response
int i = 0;
int amntRecvd = 0;
char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
i += amntRecvd;
realloc(pageContentBuffer, i * 4096 * sizeof(char));
}
realloc(pageContentBuffer, i * 4096 * sizeof(char))
لا يبدو صحيحا. إذا تلقيت 4096 بايت أولاً ، فسوف تقوم بتخصيص 4096*4096 بايت التالي ، 2*4096*4096 بايت التالي وما إلى ذلك. ربما كنت تقصد إضافة؟
أول خطأ في القفز الشرطي المعروض في سؤالك يرجع إلى استخدامك strncpy
بشكل غير صحيح. لن ينهي السلسلة المنسوخة ، عليك القيام بذلك يدويًا بعد ذلك. أفضل ثم لاستخدام memcpy.
char host[256];
int n = strlen(a)-strlen(path);
memcpy (host, a, n);
host[n] = '\0';