0

文字列として表された数値を取得し、それらに対して加算操作を実行する必要があります。これは宿題のためであり、これまでに行ったことは一種の作業です。それは正しい出力を出力しますが、私のプログラムにはメモリエラーがない必要があり、それは確かにそうではありません.

これらの初期化されていない変数で何が起こっているかについて誰かが提供できるヘルプは役に立ちます。calloc の代わりに malloc を使用していると思いましたが、それも変更しましたが、サイコロはまだありません。

ここに私の出力があります:

./a.out
strlen: 12
Old: 12122334455
New: 012122334455
Result: 167244668910

これが私のコードです: /* * ファイル: strmath.c */

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

int cmp(char *, char *, int);
void add(char *, char *, int);
char * reverse(char *);
void strReverse(char *);
char *strpadleft(char * , char,  int );

int main()
{
  char str1[] = "155122334455",
       str2[] = "12122334455"; //malloc(10);
  int len = strlen(str1) < strlen(str2)?strlen(str2):strlen(str1);
  printf("strlen: %d\n", len);
  // int result = cmp(str1, str2, len);
  // if(result > 0)
  //   printf("%s > %s\n", str1, str2);
  // else if(result < 0)
  //   printf("%s > %s\n", str2, str1);
  // else
  //   printf("%s == %s\n", str1, str2);

    add(str1, str2, len);
    return 0; 
}

int cmp(char *str1, char *str2, int longest) {
    if (strlen(str1) < strlen(str2))
        return -1;
    else if (strlen(str1) > strlen(str2))
        return 1;
    else
        return strncmp(str1, str2, longest);
}

void add(char *str1, char *str2, int longest) {

    char * num1 = strpadleft(str1, '0', longest);
    char * num2 = strpadleft(str2, '0', longest);
    strReverse(num1);
    strReverse(num2);

    char * result = calloc(longest + 2  , sizeof(char));
    int i, x, carry=0;
    for (i = 0; i < longest;i++) {
        x = (num1[i] - '0') + (num2[i] - '0') + carry;

        if (x >= 10) {
            carry = 1;
            x -= 10;
        }
        else {
            carry = 0;
        }
        result[i] = x + '0';
    }

    if (carry == 1) { result[i+1] = '1';}
    strReverse(result);
    printf("Result: %s\n", result );
    //free(result);
    //free(num1);
    //free(num2);
}

char *strpadleft(char * string, char pad, int padSize)
{
    int ssize = strlen(string);
    if (padSize <= ssize) return string;

    char *padded = calloc((padSize + 1) , sizeof(char));
    memset(padded, pad, padSize-ssize);
    padded = strcat(padded, string);
    printf("Old: %s\nNew: %s\n", string, padded);
    return padded;
}

void strReverse(char* str){
    int length = strlen(str);
    char temp;
    int i,j;
    for(i = 0, j = length-1;i < (length-1)/2; i++, j--){
        temp = str[i];
        str[i]=str[j];
        str[j] = temp;
    }
    return;
}

そして、これが私のvalgrind出力です(valgrindの完全な出力は 、SOには多すぎるため、 http: //textsnip.com/ae3c9aにあります):

==17115== Memcheck, a memory error detector
==17115== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==17115== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==17115== Command: a.out
==17115== 
==17115== Conditional jump or move depends on uninitialised value(s)
==17115==    at 0x414F76: __linkin_atfork (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x404383: ptmalloc_init.part.8 (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x407E64: malloc_hook_ini (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x4538E2: _dl_init_paths (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x415788: _dl_non_dynamic_init (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x416002: __libc_init_first (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x40173C: (below main) (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==  Uninitialised value was created
==17115==    at 0x45018A: brk (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x41370B: sbrk (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x401C95: __pthread_initialize_minimal (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x4016F0: (below main) (in /p2/hj/jsiegal/csc352/assg5/a.out)

...

==17115== Use of uninitialised value of size 8
==17115==    at 0x405B27: _int_malloc (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x408E29: calloc (in /p2/hj/jsiegal/csc352/assg5/a.out)
==17115==    by 0x401418: add (strmath.c:51)
==17115==    by 0x4012AB: main (strmath.c:31)
==17115==  Uninitialised value was created by a stack allocation
==17115==    at 0x453ADD: _dl_init_paths (in /p2/hj/jsiegal/csc352/assg5/a.out)

修理済み:

/*
 * File: strmath.c
 */

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

int cmp(char *, char *, int);
void add(char *, char *, int);
char * reverse(char *);
void strReverse(char *);
void strpadleft(char * , char *, char,  int );

int main()
{
  char str1[] = "155122334455",
       str2[] = "12122334455"; //malloc(10);
  int len = strlen(str1) < strlen(str2)?strlen(str2):strlen(str1);
  printf("strlen: %d\n", len);
  // int result = cmp(str1, str2, len);
  // if(result > 0)
  //   printf("%s > %s\n", str1, str2);
  // else if(result < 0)
  //   printf("%s > %s\n", str2, str1);
  // else
  //   printf("%s == %s\n", str1, str2);

    add(str1, str2, len);
    return 0; 
}

int cmp(char *str1, char *str2, int longest) {
    if (strlen(str1) < strlen(str2))
        return -1;
    else if (strlen(str1) > strlen(str2))
        return 1;
    else
        return strncmp(str1, str2, longest);
}

void add(char *str1, char *str2, int longest) {

    char * num1 = malloc((longest + 1) * sizeof(char));
    memset(num1, '\0', longest+1);        
    strpadleft(str1, num1, '0', longest);

    char * num2 = malloc((longest + 1) * sizeof(char));
    memset(num2, '\0', longest+1);
    strpadleft(str2, num2, '0', longest);

    strReverse(num1);
    strReverse(num2);

    char * result = malloc(longest + 2  * sizeof(char));
    memset(result, '\0', longest+2);
    int i, x, carry=0;
    for (i = 0; i < longest;i++) {
        x = (num1[i] - '0') + (num2[i] - '0') + carry;

        if (x >= 10) {
            carry = 1;
            x -= 10;
        }
        else {
            carry = 0;
        }
        result[i] = x + '0';
    }

    if (carry == 1) { result[i+1] = '1';}
    strReverse(result);
    printf("Result: %s\n", result );
    free(result);
    free(num1);
    free(num2);
}

void strpadleft(char * string, char *padded, char pad, int padSize)
{
    int ssize = strlen(string);
    if (padSize <= ssize) {
        strcpy(padded, string);
        return;
    }

    //char *padded = malloc((padSize + 1) * sizeof(char));
    //memset(padded, '\0', padSize);
    memset(padded, pad, padSize-ssize);
    padded = strcat(padded, string);
    printf("Old: %s\nNew: %s\n", string, padded);
    return;
}

void strReverse(char* str){
    int length = strlen(str);
    char temp;
    int i,j;
    for(i = 0, j = length-1;i < (length-1)/2; i++, j--){
        temp = str[i];
        str[i]=str[j];
        str[j] = temp;
    }
    return;
}

そして、valgrind の出力:

==12778== Memcheck, a memory error detector
==12778== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==12778== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==12778== Command: a.out
==12778==
strlen: 12
Old: 12122334455
New: 012122334455
Result: 167244668910
==12778==
==12778== HEAP SUMMARY:
==12778==     in use at exit: 0 bytes in 0 blocks
==12778==   total heap usage: 3 allocs, 3 frees, 40 bytes allocated
==12778==
==12778== All heap blocks were freed -- no leaks are possible
==12778==
==12778== For counts of detected and suppressed errors, rerun with: -v
==12778== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
4

1 に答える 1

2

valgrind ログは、プログラムの実行を表すものではありません。それは実際にlibcの内部関数に夢中になりました。これの明らかな理由は、使用している正確な libc バージョンの適切な抑制ファイル (誤検知のメモリ アクセス/割り当てエラーのリスト) が見つからないことです。Valgrind は自動的に解決するはずでしたが、そうはなりませんでした。システムでvalgrindを再コンパイルして正しいlibcを再度検出するか、完全に自動検出できないようにする必要があります(その後、手動で抑制ファイルを作成する必要があります)。たとえば、次を参照してください。

また、抑制ファイルのドキュメント:

さて、コードについては、各 calloc に対応する free がないことは明らかです。実際のvalgrind出力が何であるかを理解するために、valgrindの実行をコピーして貼り付けます。

(...)
==26074== 13 bytes in 1 blocks are definitely lost in loss record 1 of 2
==26074==    at 0x4C29E46: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26074==    by 0x400A15: strpadleft (in /tmp/a)
==26074==    by 0x40081A: add (in /tmp/a)
==26074==    by 0x4007D4: main (in /tmp/a)
==26074== 
==26074== 14 bytes in 1 blocks are definitely lost in loss record 2 of 2
==26074==    at 0x4C29E46: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26074==    by 0x40084B: add (in /tmp/a)
==26074==    by 0x4007D4: main (in /tmp/a)

これは何が起こっているかを示しています: calloc には一致する free がありません。add 関数には、result の calloc があります。フリーがありません。strpadleft には、結果関数の calloc があります。したがって、動的に割り当てられた変数を返します。これは、呼び出し元によって解放される必要があります。それがありません。ただし、実際の問題は、strpadleft が何も割り当てずに早期に戻る (文字列を返す) 可能性があることです。関数が新しい値を割り当てているかどうかを呼び出し元が知る方法はありません。これは間違っています。実行された操作を呼び出し元に通知するか、割り当てを均一にします (常に割り当てます)。

結論: メモリの解放は、すべての割り当てを一致させるという単純な問題です。変数を使用して割り当てを追跡します。それらが不要になったら、解放してください。

于 2013-02-24T23:03:39.773 に答える