Home > Back-end >  why the string pointer is changing its value after calling a fuction that does not affect it?
why the string pointer is changing its value after calling a fuction that does not affect it?

Time:12-14

this program is to extract the first and last names and whenever a extract the first names correctlly ( or the last names ) the other is changing its value to first ellement of the other's file

so if f1 contains Martin and f2 contains Joseph

when calling

GetPrenom(f2)

the result is

Joseph

but after calling

Getnom(f1)

the result changes to

Martin

this is my code

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

char* GetNom(FILE* f1) {
    
    char* nam = malloc(25 * sizeof(char));
    fseek (f1, 0, SEEK_END);
    int length = ftell (f1);
    fseek (f1, 0, SEEK_SET);
    char line1[length];
    fgets(line1, length, f1);
    nam = strtok(line1, " , ");
    rewind(f1);
    return nam ;
}
char* GetPrenom( FILE* f2) {
    
    char* lastname = malloc(25 * sizeof(char));
    fseek (f2, 0, SEEK_END);
    int length = ftell (f2);
    fseek (f2, 0, SEEK_SET);
    char line2[length];
    fgets(line2, length, f2);
    lastname  = strtok(line2, " ; ");
    rewind(f2);
    return lastname ;
}

int main() {
        FILE* f1 = ....; //openning the two files 
        FILE* f2 = ....;    

        char* prenom = GetPrenom(f2);
        char* nom = GetNom(f1);
        printf("%s \n", prenom);
        
    return 0;
}

what i expecte as a result is to have Joseph as first name but the result is the first str in f1 file which is Martin

so the pointer is changing its value without even passing by a function

CodePudding user response:

char* nam = malloc(25 * sizeof(char));
...
nam = strtok(line1, " , ");

is a memory leak, the initialized value is overwritten with the address of a local array. Dereferencing or trying to read this local array in main is UB. That's why you get odd results.

You can fill nam directly, something like:

fseek (f1, 0, SEEK_END);
long length = ftell(f1)   1;
fseek (f1, 0, SEEK_SET);
char *nam = malloc(length);
fgets(nam, length, f1);
char *token = strtok(nam, " , ");
rewind(f1);
return token;

Same for GetPrenom

CodePudding user response:

You carefully malloc-ed buffers, then ignored them and use stack-allocated arrays, and returned (immediately invalid) pointers to those stack arrays.

nam = strtok(line1, " , ");

does not, in any way, use the malloced memory nam originally pointed to, instead it throws away that pointer (leaking memory) and replaces it with a pointer to the first token within line1 (a pointer that's actually guaranteed to be equivalent to the address of line1, strtok just went and mutated the string to cut it off where the first delimiter began).

The second call reused the same part of the stack for its stack-allocated array, stomping all over that memory.

The code was undefined behavior, so count yourself lucky all it did was replace one valid string with another.

What you wanted would be something like:

char* GetNom(FILE* f1) {
    fseek(f1, 0, SEEK_END);
    int length = ftell(f1);
    fseek(f1, 0, SEEK_SET);
    char line1[length];
    fgets(line1, length, f1);
    char *tok = strtok(line1, " , ");  // Tokenize to get first token
    char *nam = malloc(strlen(tok)   1);  // Allocate exact space for first token, plus one for NUL
    strcpy(nam, tok);  // Copy data from token to malloc-ed buffer
    rewind(f1);
    return nam; // Return malloc-ed buffer, not pointer into transient line1
}

A similar change would be used for your other function.

  • Related