gpt4 book ai didi

c - valgrind 条件跳转或移动取决于未初始化的值

转载 作者:行者123 更新时间:2023-12-02 04:57:52 25 4
gpt4 key购买 nike

我有下面的代码,通过填充 0 作为前缀将 IP 地址固定为 15 位。

#include <stdio.h>  
#include <stdlib.h>
#include <string.h>

char *function(char *newhost){
char *IPaddr;
IPaddr = (char *)calloc(16, sizeof(char));

size_t i=0 , j= 0;
for(i=0, j=0; j<15; i++, j++){
if((newhost[strlen(newhost)-(i+1)] == '.')){ //////////line 11
if( j == 3 || j == 7 || j == 11){
IPaddr[14-j] = '.';
}else if(j<3){
while(!(j==3)){
IPaddr[14-j]='0';
j++;
}
IPaddr[14-j] = '.';
}else if(j > 3 && j<7){
while(!(j==7)){
IPaddr[14-j]='0';
j++;
}
IPaddr[14-j] = '.';
}else if(j>7 && j<11){
while(!(j==11)){
IPaddr[14-j]='0';
j++;
}
IPaddr[14-j] = '.';
}
}else if(newhost[strlen(newhost)-(i+1)] == '\0'){ ///////////line33
while(!(j==15)){
IPaddr[14-j] = '0';
j++;
}
}else{
IPaddr[14-j] = newhost[strlen(newhost)-(i+1)];
}
}
printf("IPaddr: %s\n", IPaddr);
return IPaddr;

}


int main(int argc,char *argv[]){ /////////line48
char host[100] = {'\0'};
strcpy(host, "10.0.0.2");
char *new_IP;
new_IP = function(host); ////////////line52
printf("newIP:%s\n",new_IP);
free(new_IP);

return 0;
}

代码有效,编译器既不输出错误也不输出警告。然而,valgrind 输出(valgrind --tool=memcheck --leak-check=yes --track-origins=yes test)

==22544== Conditional jump or move depends on uninitialised value(s)
==22544== at 0x8048547: function (test.c:11)
==22544== by 0x804872B: main (test.c:52)
==22544== Uninitialised value was created by a stack allocation
==22544== at 0x80486DB: main (test.c:48)
==22544==
==22544== Conditional jump or move depends on uninitialised value(s)
==22544== at 0x8048654: function (test.c:33)
==22544== by 0x804872B: main (test.c:52)
==22544== Uninitialised value was created by a stack allocation
==22544== at 0x80486DB: main (test.c:48)

谁能告诉我如何修复代码?

最佳答案

问题是在函数中,你正在做:

for (i=0, j=0; j < 15; i++, j++){
if ((newhost[strlen(newhost)-(i+1)] == '.')){

当您执行循环时,i 变得比初始化字符串的长度大,但我希望这会产生“越界”错误。但是,由于 main() 中的变量不是动态分配的,很可能 valgrind 也帮不上忙。我建议将 main() 修改为:

int main(int argc, char *argv[])
{
char *host = malloc(100);
if (host != 0)
{
strcpy(host, "10.0.0.2");
char *new_IP = function(host);
printf("newIP:%s\n", new_IP);
free(host);
free(new_IP);
}
return 0;
}

我希望 valgrind 提示更多问题,尤其是越界内存访问。

分别:

  • 由于 strlen(newhost) 在函数运行时不会更改,因此您应该在循环之外计算一次。
  • 我不确定您为什么要使用 if ((...)) 表示法。如果这是避免编译器发出有关在条件中使用赋值的警告的反射 Action ,那么您就违背了发出警告的目的。
  • 使用 sscanf() 将字符串解析为 4 个数字,然后使用 sprintf() 格式化它们会更容易吗?

    char *function(const char *newhost)
    {
    int o1, o2, o3, o4;
    char *result = 0;
    if (sscanf(newhost, "%d.%d.%d.%d", &o1, &o2, &o3, &o4) == 4)
    {
    /* Should check that values are in range 0..255 */
    result = malloc(16);
    if (result != 0)
    sprintf(result, "%.3d.%.3d.%.3d.%.3d", o1, o2, o3, o4);
    }
    return result;
    }

function() 的另一个替代实现,仅使用字符串复制:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *function(const char *newhost)
{
char *result = malloc(16);
if (result != 0)
{
strcpy(result, "000.000.000.000");
const char *beg = newhost;

for (int i = 0; i < 4; i++)
{
const char *end = strchr(beg, '.');
if (end == 0)
end = beg + strlen(beg);
memcpy(result + (i * 4) + 3 - (end - beg), beg, end - beg);
beg = end + 1;
}
}
return result;
}

int main(void)
{
char host[] = "10.0.0.2";
char *newhost = function(host);
printf("%s => %s\n", host, newhost);
free(newhost);
return 0;
}

这将计算每个段中有多少位数字,然后将其复制到结果缓冲区中的正确位置,该缓冲区已经在正确的位置填充了零和点。它避免了所有乱七八糟的原始代码,例如 3、7、11。

我还推荐一个不同的接口(interface)来运行,避免动态内存分配:

void function(const char *oldhost, char *newhost)

我们可以争论 void 还是 int,但是调用函数应该提供要写入输出的(已知的、固定大小的)缓冲区,以便避免必须进行动态内存分配。如果该函数对给定的字符串进行任何验证,您将使用 int;否则,它可以是 void。如果传递了错误的 IP 地址,现有代码大多不会报告错误。

关于c - valgrind 条件跳转或移动取决于未初始化的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17640872/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com