I have a problem with exercise 5-13 of K&R, the goal of the exercise is to make a function tail that does the same as the *nix command, here's my function:
#include <stdio.h>
#include <string.h>
#include "tail.h"
int tail(int n)
{
char *saved_lines[n];
for (int i = 0; i < n; i++)
saved_lines[i] = "\0";
int line_state[n];
for (int j = 0; j < n; j++)
line_state[j] = 0;
int num_lines = 0, i = 0;
char line[MAXLINE];
saved_lines[n - 1] = "\0";
while (get_line(line, MAXLINE) > 0)
{
for (i = 0; i < n - 1; i++)
{
strcpy(saved_lines[i], saved_lines[i + 1]);
line_state[i] = line_state[i + 1];
}
strcpy(saved_lines[n - 1], line);
line_state[n - 1] = 1;
}
printf("last %d lines: \n", n);
for (i = 0; i < n; i++)
if (line_state[i] == 1)
printf("%d: %s\n", i, saved_lines[i]);
}
problem is when I run it I get a Segmentation fault (core dumped) error, and running it through Valgrind shows the error comes from the call to strcpy:
==25284== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==25284== Bad permissions for mapped region at address 0x108E64
...I don't get why, at first strcpy had a problem with the saved_lines[i] pointers being non initialized, fixing that with
for(int i=0;i<n;i++)
saved_lines[i]="\0";
didn't help...any ideas what could cause this ? thanks in advance!
EDIT: initiated --> initialized
I believe that you've got many more problems, but one is certainly here:
int tail(int n)
{
char *saved_lines[n];
for(int i=0;i<n;i++)
saved_lines[i]="\0";
You are declaring an (variable-length) array of pointers. Then you make this pointer point to a fixed string somewhere in your data segment. Then you go and try to modify that memory. No, no.
You need to reserve memory for each of your lines. You could go for something like:
for(int i = 0; i < n; i++)
saved_lines[i] = calloc(MAXLINE, 1);
But from here there's still a lot to do. Plus you will need to free that memory later.
Related
I haven't found a similar question for the problem I've ran into. I am only guessing the root of the error, but I don't have enough knowledge to debug it. The code is as follows:
main.c
#include <stdio.h>
#include "adjacency.h"
int main()
{
FILE* textfile;
textfile = fopen("graf.txt", "r");
adjacency_matrix Graph;
create_graph(textfile);
}
adjacency.c
#include "adjacency.h"
#include <stdlib.h>
#include <stdio.h>
adjacency_matrix create_graph(FILE* input)
{
adjacency_matrix graph; int s_node, f_node;
fscanf(input, "%d", &graph.vertices);
int i, j;
graph.matrix = (int**)malloc((graph.vertices + 1) * sizeof(int*));
for (i = 0; i <= graph.vertices; i++)
graph.matrix[i] = (int*)malloc(sizeof(int));
for (i = 0; i <= graph.vertices; i++)
for (j = 0; j <= graph.vertices; j++)
graph.matrix[i][j] = 0;
for (i = 0; i <= graph.vertices; i++)
graph.matrix[i][0] = graph.matrix[0][i] = i;
while (1)
{
fscanf(input, "%d %d", &s_node, &f_node);
if (feof(input))
break;
graph.matrix[s_node][f_node] = 1;
}
return graph;
}
Everything works (I've tested printing the matrix inside the function, before returning the graph struct), but it stops after returning the adjacency_matrix struct called by my function in the main source file.
Visual Studio says
Unhandled exception at 0x77F4A879 (ntdll.dll) in dijkstra.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77F85910).
then points me to exe_common.inl, on line 292.
if (!has_cctor)
_cexit();
I would appreciate some help.
I think you need to allocate more memory for the columns of the matrix:
for (i = 0; i <= graph.vertices; i++)
graph.matrix[i] = (int*)malloc((graph.vertices + 1) * sizeof(int));
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define MAX_STRING_SIZE 20
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int N, Q;
int i, j, k, l, m, x;
char **str;
scanf("%d\n", &N);
str = (char **)malloc(sizeof(char *) * N);
for(i = 0; i < N; i++){
str[i] = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",str[i]);
}
printf("%d\n",N);
for(j = 0; j < N; j++){
printf("%s",str[j]);
printf("\n");
}
scanf("%d",&Q);
printf("%d\n",Q);
char **qry_str;
qry_str = (char **)malloc(sizeof(char *) * Q);
for(l = 0; l < Q; l++){
qry_str = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",qry_str[l]);
}
for(m = 0; m < N; m++){
printf("%s",qry_str[m]);
printf("\n");
}
for(k = 0; k < N; k++)
free(str[k]);
free(str);
for(x = 0; x < N; x++)
free(qry_str[x]);
free(qry_str);
return 0;
}
I am new to programming, and I am trying to allocate memory for two 2d strings using malloc function, but when I try to input data for the second string qry_str, (null) appears on the screen, and the program exits.
My question is:
How do we dynamically allocate memory for 2D arrays in C multiple times?
Do I need to free the memory first before using it again? (Though when I try to do that it causes segmentation fault error.)
Is this the problem due to my compiler? (I am using gcc.)
In your second case, you're overwriting qry_str inside the loop, which is not what is intended. You most probably want
for(l = 0; l < Q; l++){
qry_str[l] = malloc(MAX_STRING_SIZE * sizeof(char));
scanf("%s",qry_str[l]);
}
That said, a few suggestion:
You don't need four separate counters i, j, l, m. The first clause of for statement re-assigns the counter to 0 anyway, even if you reuse only one.
sizeof(char) is gurantted to be 1 in C. Instead, you should consider writing the statements like
qry_str[l] = malloc(MAX_STRING_SIZE * sizeof *qry_str));
to make them more robust.
Always check for the return values for scanf() family to ensure success.
This question already has answers here:
2D array dynamic memory allocation crashes [duplicate]
(2 answers)
Closed 6 years ago.
I'm a newbie trying to learn how to make dynamics arrays in C. The code doesn't give me any errors when I build it using code:blocks, but when I run it crashes. I think the crash has to do with the way I'm freeing my memory, because the code is giving me the desired output before crashing.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j;
int *p = (int *)malloc(sizeof(*p));
printf("Hello World! I have created a dynamic array of 20x30 integers! \n");
for (i = 0; i <= 19; i++)
{
p[i] = (int )malloc(sizeof(int*));
printf(" %2d ", i);
for (j = i + 1; j <= 29 + i; j++)
{
p[i] = 0;
printf("%2d", j);
}
printf("\n");
}
for (i = 0; i <= 19; i++);
{
free(p[i]);
}
free(p);
return 0;
}
Here's the problem.
First, your first malloc call allocates space for a 1-element array.
You'll want to change it from
int *p = (int *)malloc(sizeof(*p));
to
int *p = (int *)malloc(sizeof(int*) * 20);
And then your second malloc call is slightly incorrect as well.
p[i] = (int )malloc(sizeof(int*));
should be changed to
p[i] = (int *)malloc(sizeof(int));
You just put the asterisk in the wrong place.
Finally, you really only create a 20-element array. All you do in the inner for loop is assign each cell in the array the value 0 times. If you want to make a 20x30 array, you can always take the easy route and create a 1D array and use some math (which is ultimately what the compiler does with non-dynamic 2D arrays anyway):
int main()
{
int *p = (int *)malloc(sizeof(int) * 600);
...
for (i = 0; i <= 19; i++)
{
printf(" %2d ", i);
for (j = 0; j <= 29; j++)
{
p[i * 30 + j] = 0; // It's i * 30, not i * 20 because you have to skip the space that the 'j' dimension takes up.
printf("%2d", j);
}
printf("\n");
}
free((void*)p); //I found the program crashes without the void* cast
}
I've tested this code and it runs.
Hope this helps.
I know there are many topics of this kind but I've read several of them and still can't figure out what am I doing wrong.
I've successfully generated a char** array. My bubble sort function probably works as well. But when I passed the generated array to the function, only 1 row is copied.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
void sort(char** tab)
{
char* temp;
int i, j, size = sizeof(tab)/sizeof(tab[0]);
printf("%d\n", size);
for(i = 0; i < size; ++i)
{
for(j = i+1; j < size; ++j)
{
if(strcmp(tab[j-1], tab[j]) > 0)
strcpy(temp, tab[j-1]),
strcpy(tab[j-1], tab[j]),
strcpy(tab[j], temp);
}
}
for(i = 0; i < sizeof(tab)/sizeof(tab[0]); ++i)
puts(tab[i]);
}
int main()
{
srand(time(NULL));
int size = rand()%5+5, i, j, s;
char** tab = (char**)malloc(size * sizeof(char*));
for(i = 0; i < size; ++i)
{
s = rand()%9+1;
tab[i] = (char*)malloc(s+1);
for(j = 0; j < s; ++j)
tab[i][j] = 'a'+rand()%26;
tab[i][s] = 0;
}
for(i = 0; i < size; ++i)
puts(tab[i]);
puts("");
sort(tab);
return 0;
}
Here's how the code works.
And when I write size=5 before the loop in the function it returns segmentation fault.
Edit: Same with passing the size of the array as an argument:
http://ideone.com/3Wvncq
Final code
I've fixed all the problems and here's the final code.
I was misinterpreting segmentation fault as the result of assigning a fixed size instead of not allocating the temp variable.
Thank you for all the answers.
Don't calculate size inside function void sort(char** tab) . As in this function it will be calculated as -
int i, j, size = sizeof(tab)/sizeof(tab[0]); // equivalent to sizeof(char **)/sizeof(char*) in function giving wrong length as you desire.
It's length in main(size is generated using rand so no need to find it) and then pass it as argument to function sort.
Declare your function like this -
void sort(char** tab,size_t size)
And while calling from main pass length of tab to it -
sort(tab,size); // size will be number of elements in tab calculated in main
You get segmentation fault because of this -
if(strcmp(tab[j-1], tab[j]) > 0)
strcpy(temp, tab[j-1]),
strcpy(tab[j-1], tab[j]),
strcpy(tab[j], temp);
temp is uninitialized in sort and still you pass it to strcpy thus undefined behaviour . Initialize temp before passing to strcpy.Allocate memory to temp in function sort.
In your sort function you declare the temp variable:
char* temp;
Later you use it as destination (and source) for string copying:
strcpy(temp, tab[j-1]),
But nowhere in between do you make temp point anywhere, temp is uninitialized and that leads to undefined behavior and your crash.
Don't use a pointer, instead declare it as an array of the largest string size possible.
the program is supposed to compare the strings and place them in alphabetical order, but the final printf statement prints garbage...where am i going wrong here?
i have used an array of pointers to strings and declared them in the begining, i have even tried using temp as an array rather than pointer stil doesnt quite work
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int j;
int i;
char *temp;
char *string[5] = {"ibrahim","laura","peter","degea"};
for ( i = 0; i< 4;i++)
printf("%s\n", string[i]); //allocating memory
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
for ( i=0; i< 3; i++)
for(j =i+1; j<4; j++)
{
if(strcmp(string[i], string[j]) > 0)
{
strcpy(temp, string[i]);
strcpy(string[i], string[j]);
strcpy(string[j], temp);
}
}
for (i = 0; i< 4; i++)
{
printf("%s\n",string[i]);
puts("\n");
}
free(string);
free(temp);
return 0;
}
string[i] = (char*)malloc (30 * sizeof(char));
This is overwriting the existing initialized values.
EDIT
for( i = 0; i< 10 ;i++)
temp = (char*)malloc(30*sizeof(char));
WHAT? you are allocating memory over and over 10 times on a single pointer?
EDIT 2:
The original post is lost (read Edited). By the time you are reading this answer, both Mr. Jonathan Leffler and this poster migh look like absolute fools in this world.
The code originally destroyed its data array (by allocating new pointers). Now it seems to throw memory away by allocating temp four times (but Jeevan's edit reinstates the old code in indented form). The old code allocated space for strings but never initialized them (having thrown away the value that was in the array beforehand).
NB: any commentary on the code could easily be invalid by the time you're reading the commentary — the code in the question could have changed.
for (i = 0; i < 10; i++)
string[i] = malloc(30);
This code tramples out of the bounds of the string array (dimension is 5). It also loses the data originally in the array.
You need to use strcmp() to compare the strings, but you simply need to swap pointers rather than using strcpy() at all.
The comment // allocating memory beside a printf() statement is misleading, too.
This stands a chance of working. Note that there is no memory allocation:
#include <stdio.h>
#include <string.h>
int main(void)
{
int j;
int i;
char *string[] = { "ibrahim", "laura", "peter", "degea" };
for (i = 0; i < 4; i++)
printf("%s\n", string[i]);
for (i = 0; i < 3; i++)
{
for (j = i+1; j < 4; j++)
{
if (strcmp(string[i], string[j]) > 0)
{
char *temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
for (i = 0; i < 4; i++)
printf("%s\n",string[i]);
return 0;
}
Output:
ibrahim
laura
peter
degea
degea
ibrahim
laura
peter
Comment: don't try sorting thousands of strings using this sort algorithm.
You are overwriting the existing string array contents with malloc, that too 10 times.
Please use braces in your code for better understanding
for( i = 0; i< 10 ;i++)
string[i] = (char*)malloc (30 * sizeof(char));
temp = (char*)malloc(30*sizeof(char));
can be written as
for( i = 0; i< 10 ;i++) // why to allocate memory ten times, that too overwriting
{
string[i] = (char*)malloc (30 * sizeof(char));
}
temp = (char*)malloc(30*sizeof(char));
when you declare :
char *string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
the pointer *string[0] to *string[3] allocated to a address in the memory, where will stored the init values "ibrahim","laura"...
when you use malloc function for the pointer string[i] = (char*)malloc (30 * sizeof(char));
the pointer *string[0] to *string[4] will be allocated to another address in the memory. so the value at these address are different from that you initialized (ibrahim,laura).
you should use static array instead dynamic as below
char temp;
char string[5] = {
"ibrahim",
"laura",
"peter",
"degea" };
remove all the malloc, free function.