I wrote a program that worked well without any errors.
I read a text file and write the contents to an array (line by line and seperat strings in this line one by one). Then I added a second textfile and again tried to read the content but then I got some crazy segmentation faults that are only reported when I debug my program.
This is the part of the program that causes the error:
vrFile = fopen("file.txt","r");
//some temporary arrays
float taz[5000], tel[5000], ttime[5000], tvr[5000][nbins], tdbz[5000][nbins];
int size = 1024, pos;
int c;
//buffer for the line to read
char *buffervr = (char *)malloc(size);
int lin=0;
if(vrFile) {
do { // read all lines in file
pos = 0;
do{ // read one line
c = fgetc(vrFile);
if(c != EOF) buffervr[pos++] = (char)c;
if(pos >= size - 1) { // increase buffer length if line is too long - leave room for 0
size *=2;
buffervr = (char*)realloc(buffervr, size);
}
}while(c != EOF && c != '\n');
buffervr[pos] = 0;
// line is now in buffer
char *ptr;
ptr = strtok(buffervr,"\t");
int abs=1;
while(ptr != NULL) {
if(abs==1){
taz[lin] = atof(ptr);
}
else if(abs==2) {
tel[lin] = atof(ptr);
}
else if (abs==3) {
ttime[lin] = atof(ptr);
}
else {
tvr[lin][abs-4]=atof(ptr);
}
abs++;
ptr = strtok(NULL, "\t");
}
lin++;
} while(c != EOF);
fclose(vrFile);
}
//free(buffervr);
The first thing is that I get a segmentation fault when I try to allocate a buffer char *buffervr = (char *)malloc(size);. When I do this before I allocate the arrays float taz[5000], tel[5000], ttime[5000], tvr[5000][nbins], tdbz[5000][nbins]; it works?!
The second thing is that I cant read the file with c = fgetc(vrFile); although I can open it. Here I get another segmentation fault?!
Can someone tell me that went wrong?
Thank you!
EDIT: actual code:
int size = 1024, pos;
int c, cdbz;
char *buffervr = (char *)malloc(size);
char *bufferdbz = (char *)malloc(size);
int lin=0;
char *taz, *tel, *ttime, **tvr, **tdbz;
taz=(char *) malloc(5000*sizeof(char));
tel=(char *) malloc(5000*sizeof(char));
ttime=(char *) malloc(5000*sizeof(char));
tvr = malloc(5000 * sizeof(char *));
int i;
for(i = 0; i < 5000; i++) {
tvr[i] = malloc(nbins * sizeof(char));
}
tdbz = malloc(5000 * sizeof(char *));
for(i = 0; i < 5000; i++) {
tdbz[i] = malloc(nbins * sizeof(char));
}
//float taz[5000], tel[5000], ttime[5000], tvr[5000][nbins], tdbz[5000][nbins];
if(vrFile!=NULL) {
do { // read all lines in file
pos = 0;
do{ // read one line
c = fgetc(vrFile);
if(c != EOF) buffervr[pos++] = (char)c;
if(pos >= size - 1) { // increase buffer length - leave room for 0
size *=2;
buffervr = (char*)realloc(buffervr, size);
}
}while(c != EOF && c != '\n');
buffervr[pos] = 0;
// line is now in buffer
char *ptr;
ptr = strtok(buffervr,"\t");
int abs=1;
while(ptr != NULL) {
if(abs==1){
taz[lin] = (ptr);
}
else if(abs==2) {
tel[lin] = (ptr);
}
else if (abs==3) {
ttime[lin] = (ptr);
}
else {
tvr[lin][abs-4]=(ptr);
}
abs++;
ptr = strtok(NULL, "\t");
}
lin++;
} while(c != EOF);
fclose(vrFile);
}
free(buffervr);
.
.
.
int lins,abss;
for (lins=0; lins<lin; lins++)
{
time[0]=ttime[lins];
az[0]=taz[lins];
el[0]=tel[lins];
for (abss=0; abss<nbins; abss++)
{
vr[abss]=tvr[lins][abss];
//dbZ[abss]=tdbz[lins][abss];
}
}
note: time, lat, lon, az, el and vr are pointers.
EDIT: I solved my Problem this way:
vrFile = fopen("file.txt","r");
if (vrFile != NULL){
while ((getline(&line, &len, vrFile)) != -1) {
NumberOfLines++;
if(NumberOfLines == 1){
line = strtok(line, "\t");
while(line != NULL){
NumberOfDoubles++;
line = strtok(NULL, "\t");
}
}
}
}
rewind(vrFile);
int i,j;
float* taz;
float* tel;
float* ttime;
float** tvr;
float** tdbz;
//1D Arrays
taz = (float*) malloc (sizeof(float)*NumberOfLines);
tel = (float*) malloc (sizeof(float)*NumberOfLines);
ttime = (float*) malloc (sizeof(float)*NumberOfLines);
//2D Arrays
tvr = (float**) malloc (sizeof(float*)*NumberOfLines);
for(i=0;i<NumberOfLines;i++){
tvr[i] = (float*) malloc (sizeof(float)*NumberOfDoubles);
}
tdbz = (float**) malloc (sizeof(float*)*NumberOfLines);
for(i=0;i<NumberOfLines;i++){
tdbz[i] = (float*) malloc (sizeof(float)*NumberOfDoubles);
}
if (vrFile != NULL){
i = 0;
while ((getline(&line, &len, vrFile)) != -1) {
line = strtok(line, "\t");
j = -3;
while(line != NULL){
switch(j){
case -3: taz[i] = strtod(line, NULL);break;
case -2: tel[i] = strtod(line, NULL);break;
case -1: ttime[i] = strtod(line, NULL);break;
default: tvr[i][j] = strtod(line, NULL);break;
}
line = strtok(NULL, "\t");
j++;
}
i++;
}
}
Related
I have a my_string object made that contains a char pointer, a size, and a capacity. I am trying to read words from a dictionary text file into the my_string object and print them to the screen. The default capacity is 7, so when I read a word that is longer than 7 characters, I need to reallocate some space at the end of the string. I haven't been able to implement this functionality correctly yet. It seems to work correctly, but when I run it in valgrind, there is apparently a memory leak somewhere in my code. Not sure where this is coming from, because I free the entire string after the program runs. If someone could help me with this you'd be a lifesaver. Here is my driver code, and my my_string.c file:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "my_string.h"
int main(int argc, char* argv[]) {
MY_STRING hMy_String = NULL;
FILE* fp;
hMy_String = my_string_init_default();
fp = fopen("dictionary.txt", "r");
int len;
while(my_string_extraction(hMy_String, fp)) {
len = my_string_get_size(hMy_String);
if(len == 8){
my_string_insertion(hMy_String, stdout);
printf("\n");
if(fgetc(fp) == ' '){
printf("Found a space after the string\n");
}
}
}
my_string_destroy(&hMy_String);
fclose(fp);
return 0;
}
my_string.c
#include <stdio.h>
#include <stdlib.h>
#include "my_string.h"
struct my_string {
int size;
int capacity;
char* data;
};
typedef struct my_string My_String;
MY_STRING my_string_init_default(void){
//default capacity of string is 7
//initializes pointer to My_String, set to NULL for good practice
My_String* pMy_String = NULL;
//allocates memory for default string
pMy_String = (My_String*)malloc(sizeof(My_String));
if(pMy_String != NULL) {
pMy_String->size = 0;
pMy_String->capacity = 7;
pMy_String->data = (char*)malloc(sizeof(char) * pMy_String->capacity);
if(pMy_String->data == NULL) {
free(pMy_String);
pMy_String = NULL;
}
}
//returns copy of address to default string
return pMy_String;
}
MY_STRING my_string_init_c_string(char* c_string) {
int i = 0;
//initializes a pointer to a My_String
My_String* theString = NULL;
//loops through string, for every character, i increases 1
while((*c_string) != '\0'){
c_string++;
i++;
}
//resets c_strings value from before the loop
c_string = c_string - i;
i++; //i needs to be 1 greater than the length of the string
//allocation
theString = malloc(sizeof(My_String) + i);
//if there was an error, return NULL
if(theString == NULL)
return NULL;
else {
//sets the values of the object to the given values
(*theString).size = (i - 1);
(*theString).capacity = i;
(*theString).data = c_string;
}
//returns address of the initialized string
return theString;
}
int my_string_get_capacity(MY_STRING hMy_string){
return sizeof(hMy_string);
}
int my_string_get_size(MY_STRING hMy_string) {
char* str = (char*) hMy_string;
int size = 0;
while(str[size] != '\0')
size++;
return size;
}
int my_string_compare(MY_STRING hLeft_string, MY_STRING hRight_string) {
// sets the strings to pointers to the My_String data type
My_String* Left = hLeft_string;
My_String* Right = hRight_string;
//variables for lexicographical value of each string
int left_lex = 0;
int right_lex = 0;
//loops through left string, adds up left_lex value
while((*Left->data) != '\0') {
left_lex += (*Left->data);
(*Left).data++;
}
//loops through right string, adds up right_lex value
while((*Right->data) != '\0') {
right_lex += (*Right->data);
(*Right).data++;
}
//does the comparison and returns the corrosponding value
if(left_lex < right_lex){
return -1;
}else if (left_lex == right_lex) {
return 0;
}else {
return 1;
}
}
Status my_string_extraction(MY_STRING hMy_string, FILE* fp) {
My_String* pMy_string = hMy_string;
int start = 0, end = 0;
char ch;
int strLength, capacity, i;
while(!feof(fp)){
ch = fgetc(fp);
if(ch == ' ' || ch == '\t' || ch == '\n' ||ch == '\r') {
continue;
}
else {
start = ftell(fp) - 1;
end = start + 1;
break;
}
}
if(end == 0){
return FAILURE;
}
while(!feof(fp)) {
ch = fgetc(fp);
end++;
if(ch == ' ' || ch == '\t' || ch == '\n' ||ch == '\r'){
break;
}
}
strLength = end - start - 1;
(*pMy_string).size = strLength;
if(strLength == 0){
return FAILURE;
}
capacity = my_string_get_capacity(hMy_string);
if(strLength >= capacity){
hMy_string = realloc(hMy_string, strLength + 1);
}
fseek(fp, start, SEEK_SET);
char* str = (char*)hMy_string;
for(i = 0; i < strLength; i++) {
str[i] = fgetc(fp);
}
str[i] = '\0';
return SUCCESS;
}
Status my_string_insertion(MY_STRING hMy_string, FILE* fp) {
char* str = (char*)hMy_string;
if(fprintf(fp, "%s", str))
return SUCCESS;
else
return FAILURE;
}
void my_string_destroy(MY_STRING* phMy_string){
free(*phMy_string);
*phMy_string = NULL;
}
I have a function leerArch() that reads a file with information of students and returns a pointer to a dynamic array of structs t_alumno.
But when I did the debugging it seems like everything works fine except for the realloc function. The pointer *arrDin only changes once and then didn't change again.
When I print my dynamic array I get the number of elements and the students id's right but the name and surname is just the last student for every element in my array.
So I suspect my realloc function is not working properly because after debugging many times and reviewing my code I couldn't find any other flaw that could cause this problem.
Here is my struct:
typedef struct alumno{
int nro_registro;
char *nombre;
char *apellido;
}t_alumno;
and here is my function this one reads a file and returns a dynamic array of struct alumno:
t_alumno *leerArch(char *nomArch){
int r,i,legajo,j;
char c;
char *nombre = malloc(1);
char *apellido = malloc(1);
t_alumno *arrDin = malloc(sizeof(t_alumno));
//reading file
//rach line has: 123456,name,surname
FILE *arch = fopen(nomArch,"r");
r = fscanf(arch,"%d,",&legajo);
for (i=0; r!= EOF; i++){
//writing name in a string
c = fgetc(arch);
for(j=0; c!=',' && c != EOF; j++){
*(nombre+j) = c;
nombre = realloc(nombre,j+2);
c = fgetc(arch);
}
c = fgetc(arch);
*(nombre+j) = '\0';
//writing surname in a string
for(j=0; c != EOF && c!='\n'; j++){
*(apellido+j) = c;
apellido = realloc(apellido,j+2);
c = fgetc(arch);
}
*(apellido+j) = '\0';
//adding element to my array. I suspect this realloc doesn't work properly
(arrDin+i)->nro_registro = legajo;
(arrDin+i)->nombre = nombre;
(arrDin+i)->apellido = apellido;
arrDin = realloc(arrDin,(i+2)*sizeof(t_alumno));
r = fscanf(arch,"%d,",&legajo);
}
//adding an ending element
(arrDin+i)->nro_registro = 0;
(arrDin+i)->nombre = "void";
(arrDin+i)->apellido = "void";
fclose(arch);
return arrDin;
}
my file has:
170022,Juan,Rodriguez
170050,Maria,Perez
170125,Lorena,Ledesma
170245,Tomas,Garcia
And the output when I print this array is:
{170022,Tomas,Garcia}
{170050,Tomas,Garcia}
{170125,Tomas,Garcia}
{170245,Tomas,Garcia}
Printing function:
void imprimirArr(t_alumno *arrDin){
int i;
for(i=0; (arrDin+i)->nro_registro != 0; i++){
printf("\n{%d,%s,%s}",(arrDin+i)->nro_registro,(arrDin+i)->nombre,(arrDin+i)->apellido);
}
}
The problem is that you are constantly using the same pointer for "apellido" and "nombre".
Consequently, in both for loops, you are changing chars but the pointer still the same.
You must duplicate your pointer using the strdup function this way
(arrDin+i)->nombre = strdup(nombre);
(arrDin+i)->apellido = strdup(apellido);
However, I don't know if you are currently learning C language, but you can do better than what you've done here using getline and strsep functions, here is a sample code:
void print_alumnos(t_alumno **arrDin)
{
for (size_t i = 0; arrDin[i] != NULL; i++) {
printf("{%d, %s, %s}\n", arrDin[i]->nro_registro, arrDin[i]->nombre, arrDin[i]->apellido);
}
}
char **split_line(char *line)
{
char **splited_line = NULL;
char *token = NULL;
size_t i = 0;
while ((token = strsep(&line, ",")) != NULL) {
splited_line = realloc(splited_line, sizeof(char *) * (i + 2));
splited_line[i] = strdup(token);
splited_line[++i] = NULL;
}
return splited_line;
}
FILE *open_file(char *filename)
{
FILE *filestream = NULL;
if (!filename) {
return NULL;
}
filestream = fopen(filename, "r");
if (filestream == NULL) {
return NULL;
}
return filestream;
}
struct alumno **read_file(char *filename)
{
FILE *filestream = open_file(filename);
char *line = NULL;
char *tmp_ptr = NULL;
char **splited_line = NULL;
size_t i = 0;
size_t nread = 0;
struct alumno **alumnos = NULL;
if (filestream == NULL)
return NULL;
while (getline(&line, &nread, filestream) > 0) { // getting line by line
tmp_ptr = line;
if (line[strlen(line) - 1] == '\n') {
line[strlen(line) - 1] = '\0'; // delete \n because getline is keeping it
}
splited_line = split_line(line);
alumnos = realloc(alumnos, sizeof(struct alumno *) * (i + 2));
alumnos[i] = malloc(sizeof(struct alumno));
alumnos[i]->nro_registro = atoi(splited_line[0]);
alumnos[i]->apellido = splited_line[1];
alumnos[i]->nombre = splited_line[2];
alumnos[++i] = NULL;
free(tmp_ptr);
line = NULL;
nread = 0;
}
fclose(filestream);
return alumnos;
}
int main(void)
{
struct alumno **alumnos = read_file("test.txt");
print_alumnos(alumnos);
return 0;
}
I just found my mistake. So basically the char* pointer that I was putting into my array was being replaced over and over because we are working with pointers here, so I added a new malloc before writing the strings again so we get new char pointers and that got fixed.
t_alumno *leerArch(char *nomArch){
int r,i,legajo,j;
char c;
char *nombre;
char *apellido;
t_alumno *arrDin = malloc(sizeof(t_alumno));
//reading file
//rach line has: 123456,name,surname
FILE *arch = fopen(nomArch,"r");
r = fscanf(arch,"%d,",&legajo);
for (i=0; r!= EOF; i++){
//writing name in a string
c = fgetc(arch);
nombre = malloc(1);
for(j=0; c!=',' && c != EOF; j++){
*(nombre+j) = c;
nombre = realloc(nombre,j+2);
c = fgetc(arch);
}
c = fgetc(arch);
*(nombre+j) = '\0';
//writing surname in a string
apellido = malloc(1);
for(j=0; c != EOF && c!='\n'; j++){
*(apellido+j) = c;
apellido = realloc(apellido,j+2);
c = fgetc(arch);
}
*(apellido+j) = '\0';
//adding element to my array. I suspect this realloc doesn't work properly
(arrDin+i)->nro_registro = legajo;
(arrDin+i)->nombre = nombre;
(arrDin+i)->apellido = apellido;
arrDin = realloc(arrDin,(i+2)*sizeof(t_alumno));
r = fscanf(arch,"%d,",&legajo);
}
//adding an ending element
(arrDin+i)->nro_registro = 0;
(arrDin+i)->nombre = "void";
(arrDin+i)->apellido = "void";
fclose(arch);
return arrDin;
}
In the last two days i have asked a question to load struct, but i have a problem to access my struct out side my loop(a loop to load my struct). i have edited my question/and code this way:
myfile.txt
Biology,chemistry,maths,music
Mechanics,IT,Geology,music,Astronomy
football,vollyball,baseball
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define path "myfile.txt"
typedef struct student_info
{
char **cources_as_list;
} std_info;
std_info *myinfo; //a global var that will conatain student info
int line_count = 0, cource_count = 0;
char** load_file()
{
char *line = NULL;
size_t len = 0;
FILE *fp;
int indexq=0;
fp = fopen(path, "r");
if (fp == NULL)
{
perror("FILE OPEN ERROR[IN load_file]: ");
exit(1);
}
char **mydata = malloc (sizeof (char *) * 4);//aup to four elements
while (getline(&line, &len, fp) != -1)
{
strtok(line, "\n");
mydata[indexq]= strdup(line);
indexq++;
}
line_count = indexq;
return mydata;
}
char **return_cource_list(char *cources_string) {
char *token;
char **cource_list = malloc(sizeof(char *) * 10);
int index = 0;
//course_string is delimited by ",": (eg. Biology,chemistry,maths,music). parse this and add to my char ** variable.
token = strtok(cources_string, ",");
while (token != NULL)
{
cource_list[index] = strdup(token);
token = strtok(NULL, ",");
index++;
}
cource_count = index;
return cource_list;
}
int main()
{
int i, j;
char** mydata = load_file(); //returns lines as a list/char ** array from file
for (i = 0; i < line_count; i++) //line_count is the number of elements/lines in "mydata"
{
printf("line_data: %s\n",mydata[i]);//i can see all my lines!
char **std_cource_list = return_cource_list(mydata[i]);
for (j = 0; j < cource_count; j++)
{
printf("\tcourse[%d]: %s\n",j,std_cource_list[j]);//i have all my courses as a list from each line
}
//can i load my struct like this? or any option to load my struct?
myinfo[i].cources_as_list = std_cource_list;
}
// i want to see my structure elements here, (nested for loop required).
}
Am getting seg_fault error while loading my char array to my struct.
(i.e: this line: myinfo[i].cources_as_list = std_cource_list;)
You need to allocate the memory for your struct.
std_info *myinfo = malloc(sizeof(std_info));
Also don't make it global, since there is really no need for global variables in this task.
Try
std_info * myinfo = malloc(line_count * sizeof *myinfo);
This allocates memory to hold line_count objects of std_info, with myinfo pointing to the 1st.
You never allocate space for myinfo and I would suggest making it a local variable. There is almost no need for global variables except in very specific cases.
Also, you are using malloc() almost only for fixed size allocations which would be easier to manage and more efficient if you do statically in the sense that you can use arrays for that.
This might be what you're interested in
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
struct student_info
{
char **courses;
size_t size;
};
char **
load_file(const char *const path)
{
char *line;
FILE *file;
char **data;
size_t row;
size_t length;
size_t count;
file = fopen(path, "r");
if (file == NULL)
{
perror("FILE OPEN ERROR[IN load_file]: ");
return NULL; // Notify the caller that there was a problem
// but do not necessarily quit as you might
// retry with another path.
}
count = 0;
for (int chr = fgetc(file) ; chr != EOF ; chr = fgetc(file))
count += (chr == '\n') ? 1 : 0;
rewind(file);
data = malloc((count + 1) * sizeof(*data));
if (data == NULL)
{
// Perhaps notify the error
fclose(file);
return NULL;
}
data[count] = NULL; // Use as end of array delimiter
row = 0;
line = NULL;
length = 0;
while ((length = getline(&line, &length, file)) != -1)
{
// The last character is always `\n' so remove it
data[row] = malloc(length);
if (data == NULL)
{
fclose(file);
for (size_t i = row ; i >= 0 ; --i)
{
free(data[i]);
free(data);
return NULL;
}
}
data[row][length - 1] = '\0';
memcpy(data[row], line, length - 1);
++row;
}
fclose(file);
// You need to `free' this, read the documentation
free(line);
return data;
}
char **
extract_courses_as_list(const char *const input)
{
char **courses;
size_t index;
const char *tail;
const char *head;
size_t count;
head = input;
count = 0;
/* Count the number of fields to allocate memory */
while (head != NULL)
{
tail = strchr(head, ',');
if (tail != NULL)
head = tail + 1;
else
head = NULL;
count += 1;
}
index = 0;
/* Allocate memory for the list, and the sentinel */
courses = malloc((count + 1) * sizeof(*courses));
head = input;
while (head != NULL)
{
ptrdiff_t length;
/* find the next `,' in the input string */
tail = strchr(head, ',');
if (tail == NULL) /* if it's not there, it's the last one */
tail = strchr(head, '\0');
/* compute the number of characters of the field */
length = (ptrdiff_t) (tail - head);
/* allocate space to copy the string */
courses[index] = malloc(length + 1);
if (courses == NULL) /* always be safe and check */
{
for (size_t i = index ; i >= 0 ; --i)
free(courses[index]);
free(courses);
return NULL;
}
/* always remember to `null' terminate */
courses[index][length] = '\0';
/* finally, copy the string */
memcpy(courses[index], head, length);
/* check whehter it was the last field and
* update the pointer to the next one accordingly
*/
if ((tail != NULL) && (*tail != '\0'))
head = tail + 1;
else
head = NULL;
/* Don't forget the fields counter */
index++;
}
courses[count] = NULL;
return courses;
}
void
concatenate_lists(struct student_info *info, char **source)
{
char **temporary;
size_t length;
length = info->size;
for (size_t i = 0 ; source[i] != NULL ; ++i)
length++;
temporary = realloc(info->courses, length * sizeof(*temporary));
if (temporary == NULL)
return;
for (size_t i = 0 ; source[i] != NULL ; ++i)
temporary[i + info->size] = strdup(source[i]);
info->courses = temporary;
info->size = length;
}
void
free_list(char **lines)
{
if (lines == NULL)
return;
for (size_t i = 0 ; lines[i] != '\0' ; ++i)
free(lines[i]);
free(lines);
}
int
main()
{
struct student_info info;
char **lines;
lines = load_file("data.tx");
if (lines == NULL)
return -1;
info.courses = NULL;
info.size = 0;
for (size_t i = 0 ; lines[i] != NULL ; ++i)
{
char **courses;
courses = extract_courses_as_list(lines[i]);
if (courses == NULL)
continue;
concatenate_lists(&info, courses);
free_list(courses);
}
for (size_t i = 0 ; i < info.size ; ++i)
{
fprintf(stderr, "%s\n", info.courses[i]);
free(info.courses[i]);
}
free(info.courses);
free_list(lines);
return 0;
}
You will notice that I never used strdup(), the reason being that the length of the string that we want to copy is always known.
I have to dynamically allocate a pointer inside a while.
char * allocationg_memory(char [] path p) {
char message[4000];
char c;
unsigned int i = 0;
unsigned int count;
FILE *f;
//open the file
f = fopen(p, "rt");
count = 0;
//copy the contain of the file in message
if (f) {
while ((c = getc(f)) != EOF) {
count++;
message[i] = c;
i++;
}
fclose(f);
}
//allocating the memory
char *str = (char *) malloc(sizeof (char) * (count));
if (str == NULL) {
printf("error allocating memory for string\n");
exit(1);
}
//copy the message
strncpy (str, message, count);
return str;
}
void main {
char * ptr;
do {
//my path dynamically changing
path = path_of_file;
ptr = allocating_memory(path);
printf("%s", ptr);
free(ptr);
} while (1);
}
If I set ptr = NULL it gives me segmentation fault, if I don't, if the next print is bigger than the previus, the 2nd is printed over the 1st. What's wrong with my code?
For starters:
Your initial allocation is for 0 bytes.
You are trying to print what you have allocated as if it were a string.
Your loop never ends.
This works for me. Hopefully it helps
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char * allocating_memory(int c) {
char *str = malloc ( c + 1); // allow an extra for the null
strncpy ( str, "abcdefghijklmnopqustuvwxyx", c);
str[c] = '\0'; // make sure the string is null terminated
return str;
}
int main () {
char * ptr;
int counter = 2;
do {
ptr = NULL;
ptr = allocating_memory(counter);
printf("%s\n", ptr);
free(ptr);
counter++;
} while (counter < 27);
return 0;
}
I have read the other SO question about using realloc to get a new pointer to the beginning of a bigger memory address space but I cant figure out what I am doing wrong. It prints a backtrace and memory dump. I later try to access strhldr but I dont think it even gets that far.
char *strhldr = (char *)malloc(strsize);
int chrctr = 0;
if(chrctr == strsize - 3){ // when you get close
strsize = strsize*2; //double size
char *temp = realloc(strhldr, strsize); //make more room
if(temp == NULL)
printf("reallocate failed\n");
else{
strhldr = temp;
free(temp); // removed same issue
}
}
// Later attempt to add it to an array
cmdargs[i] = strhldr;
This is all within a while loop where chrctr and strsize get incremented
complete code
int argctr = 64;
char **cmdargs = (char **) malloc(argctr * sizeof(char*));
char c = getchar();
int i = 0;
while(c != '\n' && c != EOF){ //read through a String of stdin
int strsize = 32;
char *strhldr = (char *)malloc(strsize);
char *strstarthldr = strhldr;
if(c == ' ')
c = getchar();
while(c != ' ' && c != '\n' && c != EOF){
int chrctr = 0;
if(chrctr == strsize - 3){ // when you get close
strsize = strsize*2; //double size
char *temp = realloc(strhldr, strsize); //make more room
if(temp == NULL)
printf("reallocate failed\n");
else
strhldr = temp;
} //add that word to the array of strings
strhldr[chrctr] = c;
chrctr++;
c = getchar();
}
strhldr[charctr] = '\0';
//strhldr = strstarthldr;
cmdargs[i] = strhldr;
i++;
}
On success, realloc will free its argument if needed. So remove the call to free(temp).
It's not very clear to me what you are trying to do but I believe free(temp); invalidates strhldr and future read/write access to it will cause you trouble.
Second problem - your value charctr (not chrctr) is not set. Here is a version of your loop. I haven't tested it but it should be close.
if(c == ' ') {
c = getchar();
}
int chrctr = 0;
while(c != ' ' && c != '\n' && c != EOF){
if(chrctr == strsize - 3){ // when you get close
strsize = strsize*2; //double size
char *temp = realloc(strhldr, strsize); //make more room
if(temp == NULL) {
printf("reallocate failed\n");
break;
}
else {
strhldr = temp;
}
}
strhldr[chrctr] = c;
chrctr++;
c = getchar();
}
strhldr[chrctr] = 0;