程序抛出Segmentation Fault 11,Valgrind发现错误

时间:2015-04-12 22:33:59

标签: c

所以当我在成功(没有警告/错误)编译后通过valgrind运行下面的代码时,我发现了一个错误,我不确定如何修复。有问题的代码来自this exercise,我不确定我输入的代码是错误的还是代码实际上已被破坏。

代码

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "../debugging/debug_macro.h"

#define MAX_DATA 100

int read_string(char **out_string, int max_buffer) {

    *out_string = calloc(1, max_buffer + 1);
    check_mem(*out_string);

    char *result = fgets(*out_string, max_buffer, stdin);
    check(result != NULL, "Input Error.");

    return 0;

error:
    if(*out_string) free(*out_string);
    *out_string = NULL;
    return -1;
}

int read_int(int *out_int) {
    char *input = NULL;
    int rc = read_string(&input, MAX_DATA);
    check(rc == 0, "Failed to read number");

    *out_int = atoi(input);

    free(input);
    return 0;

error:
    if(input) free(input);
    return -1;
}

// Vaeriable Argument ...
int read_scan(const char*fmt, ...) {

    int rc = 0;
    int *out_int = NULL;
    char *out_char = NULL;
    char **out_string = NULL;

    int max_buffer = 0;

    va_list argp;
    va_start(argp, fmt);

    for(int i = 0; fmt[i] != '\0'; i++) {
        if(fmt[i] == '%') {
            i++;
            switch(fmt[i]) {
                case '\0':
                    sentinel("Invalid format. You ended with %%.");
                    break;
                case 'd':
                    out_int = va_arg(argp, int *);
                    rc = read_int(out_int);
                    check(rc == 0, "Failed to read int");
                    break;
                case 'c':
                    out_char = va_arg(argp, char *);
                    *out_char = fgetc(stdin);
                    break;
                case 's':
                    max_buffer = va_arg(argp, int);
                    out_string = va_arg(argp, char **);
                    rc = read_string(out_string, max_buffer);
                    check(rc == 0, "Failed to read string.");
                    break;

                default:
                    sentinel("Invalid format.");
            }
        } else {
            fgetc(stdin);
        }

        check(!feof(stdin) && !ferror(stdin), "Input error.");
    }

    va_end(argp);
    return 0;

error:
    va_end(argp);
    return -1;
}

int main(int argc, char *argv[])
{
    char *first_name = NULL;
    char initial = ' ';
    char *last_name = NULL;
    int age = 0;
    int rc = 0;

    printf("Enter First Name: ");
    rc = read_scan("%s", MAX_DATA, &first_name);
    check(rc == 0, "Failed first name.");

    printf("Enter Initial: ");
    rc = read_scan("%c\n", MAX_DATA, &initial);
    check(rc == 0, "Failed initial.");

    printf("Enter Last Name: ");
    rc = read_scan("%s", MAX_DATA, &last_name);
    check(rc == 0, "Failed last name.");

    printf("Enter Age: ");
    rc = read_scan("%d", &age);

    printf("------ [ Results ] ------\n");
    printf("Fist Name: %s.", first_name);
    printf("Initial: %c\n.", initial);
    printf("Last Name: %s.", last_name);
    printf("Age: %d\n.", age);

    free(first_name);
    free(last_name);
    return 0;

error:
    return -1;
}

输出

$ valgrind input_output/variable_input_output_functions
==14933== Memcheck, a memory error detector
==14933== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14933== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==14933== Command: input_output/variable_input_output_functions
==14933== 
Enter First Name: Adam
Enter Initial: K
==14933== Invalid write of size 1
==14933==    at 0x100001569: read_scan (variable_input_output_functions.c:66)
==14933==    by 0x1000019F4: main (variable_input_output_functions.c:106)
==14933==  Address 0x64 is not stack'd, malloc'd or (recently) free'd
==14933== 
==14933== 
==14933== Process terminating with default action of signal 11 (SIGSEGV)
==14933==  Access not within mapped region at address 0x64
==14933==    at 0x100001569: read_scan (variable_input_output_functions.c:66)
==14933==    by 0x1000019F4: main (variable_input_output_functions.c:106)
==14933==  If you believe this happened as a result of a stack
==14933==  overflow in your program's main thread (unlikely but
==14933==  possible), you can try to increase the size of the
==14933==  main thread stack using the --main-stacksize= flag.
==14933==  The main thread stack size used in this run was 8388608.
==14933== 
==14933== HEAP SUMMARY:
==14933==     in use at exit: 43,217 bytes in 429 blocks
==14933==   total heap usage: 505 allocs, 76 frees, 49,241 bytes allocated
==14933== 
==14933== LEAK SUMMARY:
==14933==    definitely lost: 0 bytes in 0 blocks
==14933==    indirectly lost: 0 bytes in 0 blocks
==14933==      possibly lost: 0 bytes in 0 blocks
==14933==    still reachable: 8,293 bytes in 3 blocks
==14933==         suppressed: 34,924 bytes in 426 blocks
==14933== Rerun with --leak-check=full to see details of leaked memory
==14933== 
==14933== For counts of detected and suppressed errors, rerun with: -v
==14933== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault: 11

有人可以告诉我发生了什么事吗?我知道错误在哪里,我只是不知道为什么错误。我是C的新手。

1 个答案:

答案 0 :(得分:1)

@BLUEPIXY的意思是:

rc = read_scan("%c\n", MAX_DATA, &initial);

应该是这样的:

rc = read_scan("%c\n", &initial);