Valgrind条件跳转或移动依赖于未初始化的值 – 所有变量已初始化

huangapple go评论76阅读模式
英文:

Valgrind Conditional jump or move depends on uninitialised value(s) - all variables initiatlized

问题

Valgrind 条件跳转或移动依赖未初始化的值

我有一个从动态分配的字符串中删除多余空格的函数,它运行正常,但我得到了一个 Valgrind 错误,涉及未初始化的变量,我无法确定它是从哪里来的。我已经初始化了所有变量,但这并没有解决错误。

以下是我的代码:

#include "main.h"

void normalize_wspace2(char *_str);

int main(void)
{
	char s[] = " ls       -la f1\t folder2 this one\t\t    ";

	printf("s initial = %s,\n", s);
	normalize_wspace2(s);
	printf("s normalized = %s,\n", s);
}

void normalize_wspace2(char *_str)
{
	size_t i = 0, j = 0;

	for (i = 0, j = 0; _str[i] != '
#include "main.h"

void normalize_wspace2(char *_str);

int main(void)
{
	char s[] = " ls       -la f1\t folder2 this one\t\t    ";

	printf("s initial = %s,\n", s);
	normalize_wspace2(s);
	printf("s normalized = %s,\n", s);
}

void normalize_wspace2(char *_str)
{
	size_t i = 0, j = 0;

	for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
	{
		if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
		{/* if whitespace is matched */
			if (i != 0)
			{/*only copy a single ' ' to normalized string*/
				_str[j] = ' ';
				i++;
				j++;
			}
			while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
			{/* loop through and ignore all other spaces*/
				i++;
			}
		}
		_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
	}
	_str[j] = '\0';
	del_twspace(_str);
}

void del_twspace(char *s)
{
	size_t i = 0;
	int last_char = -1;

	if (s == NULL)
	{
		perror("error: del_twspace passed null\n");
		return;
	}
	while (s[i] != '\0')
	{/* find the last char, ignoring any whitespace */
		if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
			last_char = i;
		i++;
	}

	s[last_char + 1] = '\0'; /* set char after last char to null */
}
'
; j++, i++)
{ if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v') {/* if whitespace is matched */ if (i != 0) {/*only copy a single ' ' to normalized string*/ _str[j] = ' '; i++; j++; } while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v') {/* loop through and ignore all other spaces*/ i++; } } _str[j] = _str[i]; /*copy non-whitespace char to normalized string */ } _str[j] = '
#include "main.h"

void normalize_wspace2(char *_str);

int main(void)
{
	char s[] = " ls       -la f1\t folder2 this one\t\t    ";

	printf("s initial = %s,\n", s);
	normalize_wspace2(s);
	printf("s normalized = %s,\n", s);
}

void normalize_wspace2(char *_str)
{
	size_t i = 0, j = 0;

	for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
	{
		if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
		{/* if whitespace is matched */
			if (i != 0)
			{/*only copy a single ' ' to normalized string*/
				_str[j] = ' ';
				i++;
				j++;
			}
			while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
			{/* loop through and ignore all other spaces*/
				i++;
			}
		}
		_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
	}
	_str[j] = '\0';
	del_twspace(_str);
}

void del_twspace(char *s)
{
	size_t i = 0;
	int last_char = -1;

	if (s == NULL)
	{
		perror("error: del_twspace passed null\n");
		return;
	}
	while (s[i] != '\0')
	{/* find the last char, ignoring any whitespace */
		if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
			last_char = i;
		i++;
	}

	s[last_char + 1] = '\0'; /* set char after last char to null */
}
'
;
del_twspace(_str); } void del_twspace(char *s) { size_t i = 0; int last_char = -1; if (s == NULL) { perror("error: del_twspace passed null\n"); return; } while (s[i] != '
#include "main.h"

void normalize_wspace2(char *_str);

int main(void)
{
	char s[] = " ls       -la f1\t folder2 this one\t\t    ";

	printf("s initial = %s,\n", s);
	normalize_wspace2(s);
	printf("s normalized = %s,\n", s);
}

void normalize_wspace2(char *_str)
{
	size_t i = 0, j = 0;

	for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
	{
		if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
		{/* if whitespace is matched */
			if (i != 0)
			{/*only copy a single ' ' to normalized string*/
				_str[j] = ' ';
				i++;
				j++;
			}
			while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
			{/* loop through and ignore all other spaces*/
				i++;
			}
		}
		_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
	}
	_str[j] = '\0';
	del_twspace(_str);
}

void del_twspace(char *s)
{
	size_t i = 0;
	int last_char = -1;

	if (s == NULL)
	{
		perror("error: del_twspace passed null\n");
		return;
	}
	while (s[i] != '\0')
	{/* find the last char, ignoring any whitespace */
		if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
			last_char = i;
		i++;
	}

	s[last_char + 1] = '\0'; /* set char after last char to null */
}
'
)
{/* find the last char, ignoring any whitespace */ if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n') last_char = i; i++; } s[last_char + 1] = '
#include "main.h"

void normalize_wspace2(char *_str);

int main(void)
{
	char s[] = " ls       -la f1\t folder2 this one\t\t    ";

	printf("s initial = %s,\n", s);
	normalize_wspace2(s);
	printf("s normalized = %s,\n", s);
}

void normalize_wspace2(char *_str)
{
	size_t i = 0, j = 0;

	for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
	{
		if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
		{/* if whitespace is matched */
			if (i != 0)
			{/*only copy a single ' ' to normalized string*/
				_str[j] = ' ';
				i++;
				j++;
			}
			while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
			{/* loop through and ignore all other spaces*/
				i++;
			}
		}
		_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
	}
	_str[j] = '\0';
	del_twspace(_str);
}

void del_twspace(char *s)
{
	size_t i = 0;
	int last_char = -1;

	if (s == NULL)
	{
		perror("error: del_twspace passed null\n");
		return;
	}
	while (s[i] != '\0')
	{/* find the last char, ignoring any whitespace */
		if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
			last_char = i;
		i++;
	}

	s[last_char + 1] = '\0'; /* set char after last char to null */
}
'
; /* set char after last char to null */
}

Valgrind 输出:

$ valgrind -s --leak-check=full --show-leak-kinds=all --track-origins=yes ./a.out

==8876== Memcheck, a memory error detector
==8876== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8876== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==8876== Command: ./a.out
==8876== 
==8876== Conditional jump or move depends on uninitialised value(s)
==8876==    at 0x109323: normalize_wspace2 (in /workspaces/103507869/functions/cln/a.out)
==8876==    by 0x1091F4: main (in /workspaces/103507869/functions/cln/a.out)
==8876==  Uninitialised value was created by a stack allocation
==8876==    at 0x109169: main (in /workspaces/103507869/functions/cln/a.out)
==8876== 
s initial =  ls       -la f1	 folder2 this one		    ,
s normalized = ls -la f1 folder2 this one ,
==8876== 
==8876== HEAP SUMMARY:
==8876==     in use at exit: 0 bytes in 0 blocks
==8876==   total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated
==8876== 
==8876== All heap blocks were freed -- no leaks are possible
==8876== 
==8876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==8876== 
==8876== 1 errors in context 1 of 1:
==8876== Conditional jump or move depends on uninitialised value(s)
==8876==    at 0x109323: normalize_wspace2 (in /workspaces/103507869/functions/cln/a.out)
==8876==    by 0x1091F4: main (in /workspaces/103507869/functions/cln/a.out)
==8876==  Uninitialised value was created by a stack allocation
==8876==    at 0x109169: main (in /workspaces/103507869/functions/cln/a.out)
==8876== 
==8876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

希望这可以帮助你找出 Valgrind 报错的问题所在。

英文:

Valgrind Conditional jump or move depends on uninitialised value(s)

I have a function that removes excess whitespace from a dynamically allocated string, it works fine but I get a valgrind error concerning uninitialized variables and I can't seem to pin point where it is coming from. I have all variables initialized but that doesnt resolve the error.

Here's my code below

#include "main.h"

void normalize_wspace2(char *_str);

int main(void)
{
	char s[] = " ls       -la f1\t folder2 this one\t\t    ";

	printf("s initial = %s,\n", s);
	normalize_wspace2(s);
	printf("s normalized = %s,\n", s);
}
void normalize_wspace2(char *_str)
{
	size_t i = 0, j = 0;

	for (i = 0, j = 0; _str[i] != '
#include "main.h"
void normalize_wspace2(char *_str);
int main(void)
{
char s[] = " ls       -la f1\t folder2 this one\t\t    ";
printf("s initial = %s,\n", s);
normalize_wspace2(s);
printf("s normalized = %s,\n", s);
}
void normalize_wspace2(char *_str)
{
size_t i = 0, j = 0;
for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
{
if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* if whitespace is matched */
if (i != 0)
{/*only copy a single ' ' to normalized string*/
_str[j] = ' ';
i++;
j++;
}
while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* loop through and ignore all other spaces*/
i++;
}
}
_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
}
_str[j] = '\0';
del_twspace(_str);
}
void del_twspace(char *s)
{
size_t i = 0;
int last_char = -1;
if (s == NULL)
{
perror("error: del_twspace passed null\n");
return;
}
while (s[i] != '\0')
{/* find the last char, ignoring any whitespace */
if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
last_char = i;
i++;
}
s[last_char + 1] = '\0'; /* set char after last char to null */
}
'; j++, i++) { if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v') {/* if whitespace is matched */ if (i != 0) {/*only copy a single ' ' to normalized string*/ _str[j] = ' '; i++; j++; } while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v') {/* loop through and ignore all other spaces*/ i++; } } _str[j] = _str[i]; /*copy non-whitespace char to normalized string */ } _str[j] = '
#include "main.h"
void normalize_wspace2(char *_str);
int main(void)
{
char s[] = " ls       -la f1\t folder2 this one\t\t    ";
printf("s initial = %s,\n", s);
normalize_wspace2(s);
printf("s normalized = %s,\n", s);
}
void normalize_wspace2(char *_str)
{
size_t i = 0, j = 0;
for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
{
if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* if whitespace is matched */
if (i != 0)
{/*only copy a single ' ' to normalized string*/
_str[j] = ' ';
i++;
j++;
}
while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* loop through and ignore all other spaces*/
i++;
}
}
_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
}
_str[j] = '\0';
del_twspace(_str);
}
void del_twspace(char *s)
{
size_t i = 0;
int last_char = -1;
if (s == NULL)
{
perror("error: del_twspace passed null\n");
return;
}
while (s[i] != '\0')
{/* find the last char, ignoring any whitespace */
if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
last_char = i;
i++;
}
s[last_char + 1] = '\0'; /* set char after last char to null */
}
'; del_twspace(_str); } void del_twspace(char *s) { size_t i = 0; int last_char = -1; if (s == NULL) { perror("error: del_twspace passed null\n"); return; } while (s[i] != '
#include "main.h"
void normalize_wspace2(char *_str);
int main(void)
{
char s[] = " ls       -la f1\t folder2 this one\t\t    ";
printf("s initial = %s,\n", s);
normalize_wspace2(s);
printf("s normalized = %s,\n", s);
}
void normalize_wspace2(char *_str)
{
size_t i = 0, j = 0;
for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
{
if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* if whitespace is matched */
if (i != 0)
{/*only copy a single ' ' to normalized string*/
_str[j] = ' ';
i++;
j++;
}
while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* loop through and ignore all other spaces*/
i++;
}
}
_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
}
_str[j] = '\0';
del_twspace(_str);
}
void del_twspace(char *s)
{
size_t i = 0;
int last_char = -1;
if (s == NULL)
{
perror("error: del_twspace passed null\n");
return;
}
while (s[i] != '\0')
{/* find the last char, ignoring any whitespace */
if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
last_char = i;
i++;
}
s[last_char + 1] = '\0'; /* set char after last char to null */
}
') {/* find the last char, ignoring any whitespace */ if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n') last_char = i; i++; } s[last_char + 1] = '
#include "main.h"
void normalize_wspace2(char *_str);
int main(void)
{
char s[] = " ls       -la f1\t folder2 this one\t\t    ";
printf("s initial = %s,\n", s);
normalize_wspace2(s);
printf("s normalized = %s,\n", s);
}
void normalize_wspace2(char *_str)
{
size_t i = 0, j = 0;
for (i = 0, j = 0; _str[i] != '\0'; j++, i++)
{
if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* if whitespace is matched */
if (i != 0)
{/*only copy a single ' ' to normalized string*/
_str[j] = ' ';
i++;
j++;
}
while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* loop through and ignore all other spaces*/
i++;
}
}
_str[j] = _str[i]; /*copy non-whitespace char to normalized string */
}
_str[j] = '\0';
del_twspace(_str);
}
void del_twspace(char *s)
{
size_t i = 0;
int last_char = -1;
if (s == NULL)
{
perror("error: del_twspace passed null\n");
return;
}
while (s[i] != '\0')
{/* find the last char, ignoring any whitespace */
if (s[i] != ' ' && s[i] != '\t' && s[i] != '\n')
last_char = i;
i++;
}
s[last_char + 1] = '\0'; /* set char after last char to null */
}
'; /* set char after last char to null */ }

Valgrind output


$ valgrind -s --leak-check=full --show-leak-kinds=all --track-origins=yes ./a.out

==8876== Memcheck, a memory error detector
==8876== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8876== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==8876== Command: ./a.out
==8876== 
==8876== Conditional jump or move depends on uninitialised value(s)
==8876==    at 0x109323: normalize_wspace2 (in /workspaces/103507869/functions/cln/a.out)
==8876==    by 0x1091F4: main (in /workspaces/103507869/functions/cln/a.out)
==8876==  Uninitialised value was created by a stack allocation
==8876==    at 0x109169: main (in /workspaces/103507869/functions/cln/a.out)
==8876== 
s initial =  ls       -la f1	 folder2 this one		    ,
s normalized = ls -la f1 folder2 this one ,
==8876== 
==8876== HEAP SUMMARY:
==8876==     in use at exit: 0 bytes in 0 blocks
==8876==   total heap usage: 1 allocs, 1 frees, 4,096 bytes allocated
==8876== 
==8876== All heap blocks were freed -- no leaks are possible
==8876== 
==8876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==8876== 
==8876== 1 errors in context 1 of 1:
==8876== Conditional jump or move depends on uninitialised value(s)
==8876==    at 0x109323: normalize_wspace2 (in /workspaces/103507869/functions/cln/a.out)
==8876==    by 0x1091F4: main (in /workspaces/103507869/functions/cln/a.out)
==8876==  Uninitialised value was created by a stack allocation
==8876==    at 0x109169: main (in /workspaces/103507869/functions/cln/a.out)
==8876== 
==8876== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

答案1

得分: 1

以下是翻译好的部分:

问题出现在尾随空白处:
在这个循环之后

while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* 循环并忽略所有其他空格 */
    i++;
}

i 将会是 _str 中尾随的 '\0' 的索引。然后它会再次被 for() 增加,因此对 _str[i] != '0' 的下一个检查已经超出了 _str 的范围。

要解决这个问题,你可以添加:

if (_str[i] == '
if (_str[i] == '\0' ) {
    _str[j] = '\0';
    break;
}
'
) {
_str[j] = '
if (_str[i] == '\0' ) {
    _str[j] = '\0';
    break;
}
'
;
break; }

在 while 循环之后,或者你可以将循环体更改为:

if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
{/* 如果匹配到空白字符 */
    if (i != 0)
    {/* 只复制一个空格到规范化的字符串中 */
        _str[j] = ' ';
         j++;
    }
    while (_str[i+1] == ' ' || _str[i+1] == '\t' || _str[i+1] == '\v')
    {/* 循环并忽略所有其他空格 */
        i++;
    }
} else {
    _str[j] = _str[i]; /* 将非空白字符复制到规范化的字符串中 */
    j++;
}

一个完全不同的解决方案,避免在 for() 循环中写入 i,可以如下所示(顺便说一句:我在这里去掉了前导的 _,因为这些是保留名字):

bool whitespace = false;      
int j = 0;
for( int i=0; str[i] != '
bool whitespace = false;      
int j = 0;
for( int i=0; str[i] != '\0'; ++ ) {
     if( isspace(str[i]) ) { // 太懒得写空白字符 
         if( j > 0 ) {
             whitespace  = true;
         }
     } else {
         if( whitespace ) {
             str[j++] = ' ';
             whitespace = false;
         }
         str[j++] = str[i];
     }
}
str[j] = '\0';
'
; ++ ) {
if( isspace(str[i]) ) { // 太懒得写空白字符 if( j > 0 ) { whitespace = true; } } else { if( whitespace ) { str[j++] = ' '; whitespace = false; } str[j++] = str[i]; } } str[j] = '
bool whitespace = false;      
int j = 0;
for( int i=0; str[i] != '\0'; ++ ) {
     if( isspace(str[i]) ) { // 太懒得写空白字符 
         if( j > 0 ) {
             whitespace  = true;
         }
     } else {
         if( whitespace ) {
             str[j++] = ' ';
             whitespace = false;
         }
         str[j++] = str[i];
     }
}
str[j] = '\0';
'
;
英文:

The problem occurs with trailing whitespace:
After this loop

        while (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
        {/* loop through and ignore all other spaces*/
            i++;
        }

i will already be the index of the trailing '\0' in _str. Then it's incremented again by for() and so the next check for _str[i] != \0' is already beyond the bounds of _str.

Do solve its you could just add

        if (_str[i] == '
        if (_str[i] == '\0' ) {
_str[j] = '\0';
break;
}
' ) { _str[j] = '
        if (_str[i] == '\0' ) {
_str[j] = '\0';
break;
}
'; break; }

after the while loop or you change the loop body to

    if (_str[i] == ' ' || _str[i] == '\t' || _str[i] == '\v')
    {/* if whitespace is matched */
        if (i != 0)
        {/*only copy a single ' ' to normalized string*/
            _str[j] = ' ';
             j++;
       }
        while (_str[i+1] == ' ' || _str[i+1] == '\t' || _str[i+1] == '\v')
        {/* loop through and ignore all other spaces*/
            i++;
        }
    } else {
        _str[j] = _str[i]; /*copy non-whitespace char to normalized string */
        j++;
    }

A completely different solution which avoids writing to i within the for() loop could look like that (btw: I remove leading _ here, because these are resevered names:

    bool whitespace = false;      
    int j = 0;
    for( int i=0; str[i] != '
    bool whitespace = false;      
int j = 0;
for( int i=0; str[i] != '\0'; ++ ) {
if( isspace(str[i]) ) { // too lazy to write whitespace characters 
if( j > 0 ) {
whitespace  = true;
}
} else {
if( whitespace ) {
str[j++] = ' ';
whitespace = false;
}
str[j++] = str[i];
}
}
str[j] = '\0';
'; ++ ) { if( isspace(str[i]) ) { // too lazy to write whitespace characters if( j > 0 ) { whitespace = true; } } else { if( whitespace ) { str[j++] = ' '; whitespace = false; } str[j++] = str[i]; } } str[j] = '
    bool whitespace = false;      
int j = 0;
for( int i=0; str[i] != '\0'; ++ ) {
if( isspace(str[i]) ) { // too lazy to write whitespace characters 
if( j > 0 ) {
whitespace  = true;
}
} else {
if( whitespace ) {
str[j++] = ' ';
whitespace = false;
}
str[j++] = str[i];
}
}
str[j] = '\0';
';

huangapple
  • 本文由 发表于 2023年5月26日 17:04:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76339288.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定