1. ホーム
  2. c

[解決済み] サイズ 1 の無効な書き込み

2022-02-05 14:16:44

質問

パラメータに従って元の文字列を文字列の配列に保存された複数の文字列に分割する私の分割関数の大部分を修正しました:プログラムは私が欲しかった値を返しますが、valgrindは私に次のようにヒットしました。

abc,defg
pasa
pasa
pasa
pasa
pasa
pasa
pasa
pasa
pasa
==2938== Conditional jump or move depends on uninitialised value(s)
==2938==    at 0x4C2DB3C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2938==    by 0x400912: split (strutil.c:31)
==2938==    by 0x400A06: main (strutil.c:45)
==2938==  Uninitialised value was created by a stack allocation
==2938==    at 0x400723: split (strutil.c:9)
==2938== 
==2938== Conditional jump or move depends on uninitialised value(s)
==2938==    at 0x4C31577: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2938==    by 0x40097F: split (strutil.c:34)
==2938==    by 0x400A06: main (strutil.c:45)
==2938==  Uninitialised value was created by a stack allocation
==2938==    at 0x400723: split (strutil.c:9)
==2938== 
==2938== Conditional jump or move depends on uninitialised value(s)
==2938==    at 0x4C31631: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2938==    by 0x40097F: split (strutil.c:34)
==2938==    by 0x400A06: main (strutil.c:45)
==2938==  Uninitialised value was created by a stack allocation
==2938==    at 0x400723: split (strutil.c:9)
==2938== 
==2938== Conditional jump or move depends on uninitialised value(s)
==2938==    at 0x4C3164F: __strncpy_sse2_unaligned (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2938==    by 0x40097F: split (strutil.c:34)
==2938==    by 0x400A06: main (strutil.c:45)
==2938==  Uninitialised value was created by a stack allocation
==2938==    at 0x400723: split (strutil.c:9)
==2938== 
==2938== 
==2938== More than 10000000 total errors detected.  I'm not reporting any more.
==2938== Final error counts will be inaccurate.  Go fix your program!
==2938== Rerun with --error-limit=no to disable this cutoff.  Note
==2938== that errors may occur in your program without prior warning from
==2938== Valgrind, because errors are no longer being displayed.
==2938== 
abc
defg

そして、私のコードは

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

char** split(const char* str, char sep){
size_t cant = 2;
size_t i = 0;
for(i = 0; i < strlen(str); i++){
    if(str[i] == sep)
        cant ++;
}
size_t corte[cant];
corte[0] = 0;
size_t j = 1;
size_t cant_corte[cant];
for(i = 0; i < cant; i++)
    cant_corte[i] = 0;
for(i = 0; i <= strlen(str); i++){
    if(str[i] == sep || str[i] == '\0'){
        corte[j] = i + 1;
        cant_corte[j - 1] = corte[j] - corte[j - 1];
        j++;
    }
}

char** strv = malloc(sizeof(char*) * cant);
    if (strv == NULL)return NULL;
for(i=0; i < cant; i++){
    strv[i] = malloc(sizeof(char) * cant_corte[i]); //line 30
    if (strv[i] == NULL)return NULL;
    memcpy(strv[i], str + corte[i], cant_corte[i]);
    strv[i][cant_corte[i] -1] = '\0'; //line 33
}
strv[cant - 1] = NULL;
return strv;
}

int main(){
char* eje = "abc,defg";
printf("%s\n", eje);
char r = ',';
char** prueba = split(eje, r);
printf("%s\n", prueba[0]);
printf("%s\n", prueba[1]);
getchar();
return 0;
}

同じ値で問題が発生しているように見えますが、問題が見つからないので、どこに問題があるのかわかりません。

EDIT コードを編集したら、valgrind が私を表示するようになりました。

==3751== Invalid write of size 1
==3751==    at 0x4009DB: split (strutil.c:33)
==3751==    by 0x400A64: main (strutil.c:43)
==3751==  Address 0x520457f is 1 bytes before a block of size 0 alloc'd
==3751==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3751==    by 0x400949: split (strutil.c:30)
==3751==    by 0x400A64: main (strutil.c:43)

30行目のmallocに+1を追加してみましたが、代わりに ...block of size 1 aloc'd... と表示されました。と表示されてしまいます。

解決方法は?

で終わってしまう。 cant_corte[i]0 を、そして、あなたは strv[i][cant_corte[i] -1] = '\0';

だから strv[i][-1] は書き込むのに有効なアドレスではありません。

の使い方を学ぶことをお勧めします。 valgrindgdb で説明しているように http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver-simple