简体   繁体   中英

gcc: Why does two different variables have the same value after call?

I'm wondering how I can fix this. I admit I'm not that great at C to begin with. I've commented the code below to show what is happening. If I make the function call, then print out the values immediately after each function call, then the results are correct. But, if I print out the values after doing all the function calls, it only prints out the last value for both variables!

Why is it doing this and how to I fix it?

NOTE: I'm doing this in Linux using gcc version 4.9.2 (Debian 4.9.2-10)

/* Get first/last of string */

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

void strtoarr(unsigned char *input, int len, unsigned char output[128]);
char* substr(unsigned char input[128], int start_pos, int num_chars);

int main(void)
{

    unsigned char myArr[128];
    unsigned char *myStr = (unsigned char*)"79356e39486a556e576d6c3279443267516834376137333131387246474b3137";
    char *strFirst;
    char *strLast;

    /* For the project I'm working on, I'm going to need this as an array of characters anyway. */
    strtoarr(myStr, 64, myArr);
    printf("Original String: %s\n", myArr);

    printf("\n");

    /* If I print the string after each call, it works.
       Prints out:
       Try 1 First 32: 79356e39486a556e576d6c3279443267
       Try 1 Last 32: 516834376137333131387246474b3137
     */
    strFirst = substr(myArr, 0, 32);
    printf("Try 1 First 32: %s\n", strFirst);
    strLast = substr(myArr, 32, 32);
    printf("Try 1 Last 32: %s\n", strLast);

    printf("\n");

    /* FIXME: Why does it print the exact same thing if I print out after both calls?
       Prints out:
       Try 2 First 32: 516834376137333131387246474b3137
       Try 2 Last 32: 516834376137333131387246474b3137
     */
    strFirst = substr(myArr, 0, 32);
    strLast = substr(myArr, 32, 32);
    printf("Try 2 First 32: %s\n", strFirst);
    printf("Try 2 Last 32: %s\n", strLast);

    return 0;
}

char* substr(unsigned char input[128], int start_pos, int num_chars) {
    char *result = calloc(num_chars * 2 + 1, sizeof(char*));
    int i;

    for(i = start_pos; i < (num_chars + start_pos); i++) {
        result[i - start_pos] = input[i];
    }
    result[(i - start_pos) + 1] = '\0';
    free(result);

    return result;
}


/* Convert string to array of characters */
void strtoarr(unsigned char *input, int len, unsigned char output[128]) {
    int i;

    for(i = 0; i < len + 1; i++) {
        output[i] = input[i];
    }
    output[i + 1] = '\0';
}

Returning a pointer to freed memory (then reading from said memory) is undefined behaviour.

Change your substr to not free the memory:

char* substr(unsigned char input[128], int start_pos, int num_chars) {
    char* result = calloc(num_chars + 1, sizeof(char));

    strncpy(result, (char*)input + start_pos, num_chars);

    return result;
}

Remember to free this memory on the caller level.

In your substr function, you alloc some memory and copy data in it which is fine. But then you free it and return a pointer to freed memory. From that on, using that pointer is undefined behaviour!

What happens under the hood for your implementation and in that context is that the same pointer value is returned by both calls to malloc, what explains that both pointers show same last value. But you could also could have got an error or any other display.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM