Why am I getting segmentation fault? I have listed my code below.
Please tell if anyone knows what is my fault here and how do I correct it?
What I am trying to do here
I am trying to take numbers as input and for them I have to output a string of characters.
Problem
link to the problem is here.
The code of my proposed solution
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
long long int n, k;
char manku[] = { 'm', 'a', 'n', 'k', 'u' };
char l[10000000];
int t, i = 0, j, p;
scanf("%d", &t);
while (t > 0)
{
scanf("%lld", &n);
while (n > 0)
{
j = n % 5;
if (j == 0)
l[i] = manku[4];
else
l[i] = manku[j - 1];
n = n / 5;
i++;
}
p = strlen(l);
for (i = 0; i < p; i++)
l[i] = l[p - 1 - i];
for (i = 0; i < p; i++)
printf("%c", l[i]);
t--;
}
return 0;
}
char l[10000000];
This huge array is overflowing your stack memory.
The stack memory segment is an area of memory allotted for automatic variables and its size is fairly small. It is not a good idea to have such a huge array in stack.
Try to allocate it dynamically, like this:
char *l;
l = malloc(10000000); //note: size of char is 1
With this, the memory allocated to l in heap segment. Make sure to free it once you done with it.
Alternatively, you can make l a global variable or a static local variable so that it will go in Data Segment.
You are getting a segmentation fault when you start running your binary because you are running out of stack memory due to the big size of your array char l[10000000] (you can check the size of your stack by running
$ ulimit -s
in your shell).
There are at least two solutions to this:
Increase the size of your stack. You can do this by running, e.g.,
$ ulimit -s unlimited
in your shell before running the binary.
Use malloc to allocate the l array, so that it is allocated in the heap rather than in the stack.
Firstly, initialize the variable i after scanning n.
while(t>0) {
scanf("%lld",&n);
i = 0; /* initialize i every time here */
while(n>0) {
/* some code */
}
}
Also instead of creating stack created array like char l[10000000]; create the dynamic array once before while loop and free the dynamically allocated memory once done. for e.g
char *l = malloc(SIZE); /* define the SIZE */
...
...
free(l);
Short Answer: The segmentation fault is caused by char l[10000000];. Decalring char l[26]; is sufficient.
Details
As others said the allocation char l[10000000]; causes the segmentation fault. You do not need this much memory. The question stated that the maximum value for n is 10^18. Thus the maximum length of a word would be 26 characters. Thus, char l[26]; is sufficient.
Explanation: It is given that you have 10^18 options to arrange k characters. Each charater has 5 options and thus the number of options to arrange these characters is 5^k. Now, you just have to find k:
5^k = 10^18 ==> k = log_5(10^18) ~= 25.75218 < 26
Implementation
Regarding the implementation, you have few wrong things going on.
You do not set i = 0; after each input scan.
Your can not use strlen without the terminating null-character. You should add l[i] = '\0'; above p = strlen(l);.
Your second for loop, the one that should revert the string, is not working properly. Each step changes the string and the steps after it use the changed string (instead of working with the original one).
Regarding the algorithm, it does not work properly as well. I can give you a hint: this problem is similar to counting in base-5.
Comments
The things above are just few things that I have noticed. I think you should consider rewriting the code since it may still contaion small flaws.
Another tip: for printing strings (character arrays in c) you can use
printf("%s", str);
Assuming that str is an array of character that ends with the terminating null-character. Some more information here.
Related
When I try to run my programme with this function, I get a segmentation fault, because stack buffer gets overflown. Can somebody help?
void converttobin(int a, int b, char x) {
char binary[81];
int number = 0;
char bit;
char original[81];
int dividing = 0;
number = a;
size_t len = strlen(binary);
while (a != 0) {
dividing = a % 2;
bit = dividing + '0';
binary[len++] = bit;
binary[len] = '\0';
a = a / 2;
}
if (number == 0) {
a = 0;
bit = 0 + '0';
binary[len++] = bit;
binary[len] = '\0';
}
strncpy(original, binary, strlen(original));
reverse(binary, number, b);
comparing(binary, original,number, b, x);
memset(binary, 0, strlen(binary));
memset(original, 0, strlen(original));
}
As #Christian Gibbons points out in his comment, binary is un-initialised when you call strlen on it. But what does this mean?
strlen walks the array, starting at the first element, counting non-terminating characters. It doesn't stop until it finds a termination ('\0'). If you're unlucky, that can be a long way into the un-initialised data, and likely to be well past the 81 chars you've allocated. After a while, strlen starts looking at memory it's not allowed to and you get a segmentation fault (your program has explored outside its allocated segment of memory).
You can resolve this in a few ways. The simplest is:
char binary[81] = { 0 };
This asks the compiler to set the first element to zero (the terminating character). That's good, because it's the first character strlen will see and stop immediately, reporting your string has length 0.
But looking at your algorithm, you could just ditch the call to strlen altogether and do:
size_t len = 0;
But even if you take this approach, it's good practice to initialise your buffers with safe values anyway.
I've written a piece of code that uses a static array of size 3000.
Ordinarily, I would just use a for loop to scan in 3000 values, but it appears that I can only ever scan in a maximum of 2048 numbers. To me that seems like an issue with memory allocation, but I'm not sure.
The problem arises because I do not want a user to input the amount of numbers they intend to input. They should only input whatever amount of numbers they want, terminate the scan by inputting 0, after which the program does its work. (Otherwise I would just use malloc.)
The code is a fairly simple number occurrence counter, found below:
int main(int argc, char **argv)
{
int c;
int d;
int j = 0;
int temp;
int array[3000];
int i;
// scanning in elements to array (have just used 3000 because no explicit value for the length of the sequence is included)
for (i = 0; i < 3000; i++)
{
scanf("%d", &array[i]);
if (array[i] == 0)
{
break;
}
}
// sorting
for(c = 0; c < i-1; c++) {
for(d = 0; d < i-c-1; d++) {
if(array[d] > array[d+1]) {
temp = array[d]; // swaps
array[d] = array[d+1];
array[d+1] = temp;
}
}
}
int arrayLength = i + 1; // saving current 'i' value to use as 'n' value before reset
for(i = 0; i < arrayLength; i = j)
{
int numToCount = array[i];
int occurrence = 1; // if a number has been found the occurence is at least 1
for(j = i+1; j < arrayLength; j++) // new loops starts at current position in array +1 to check for duplicates
{
if(array[j] != numToCount) // prints immediately after finding out how many occurences there are, else adds another
{
printf("%d: %d\n", numToCount, occurrence);
break; // this break keeps 'j' at whatever value is NOT the numToCount, thus making the 'i = j' iterator restart the process at the right number
} else {
occurrence++;
}
}
}
return 0;
}
This code works perfectly for any number of inputs below 2048. An example of it not working would be inputting: 1000 1s, 1000 2s, and 1000 3s, after which the program would output:
1: 1000
2: 1000
3: 48
My question is whether there is any way to fix this so that the program will output the right amount of occurrences.
To answer your title question: The size of an array in C is limited (in theory) only by the maximum value that can be represented by a size_t variable. This is typically a 32- or 64-bit unsigned integer, so you can have (for the 32-bit case) over 4 billion elements (or much, much more in 64-bit systems).
However, what you are probably encountering in your code is a limit on the memory available to the program, where the line int array[3000]; declares an automatic variable. Space for these is generally allocated on the stack - which is a chunk of memory of limited size made available when the function (or main) is called. This memory has limited size and, in your case (assuming 32-bit, 4-byte integers), you are taking 12,000 bytes from the stack, which may cause problems.
There are two (maybe more?) ways to fix the problem. First, you could declared the array static - this would make the compiler pre-allocate the memory, so it would not need to be taken from the stack at run-time:
static int array[3000];
A second, probably better, approach would be to call malloc to allocate memory for the array; this assigns memory from the heap - which has (on almost all systems) considerably more space than the stack. It is often limited only by the available virtual memory of the operating system (many gigabytes on most modern PCs):
int *array = malloc(3000 * sizeof(int));
Also, the advantage of using malloc is that if, for some reason, there isn't enough memory available, the function will return NULL, and you can test for this.
You can access the elements of the array in the same way, using array[i] for example. Of course, you should be sure to release the memory when you've done with it, at the end of your function:
free(array);
(This will be done automatically in your case, when the program exits, but it's good coding style to get used to doing it explicitly!)
i am new to c programming . i made a parser which gets a char array (a command which later should also have arguments) and should divide it into smaller arrays. From there i want to further analize each array on its own. There is probably a better way to solve this problem but i really just want to understand what is happening here.
when i run the debugger (yes i did run the debugger) it tells me there is a segmentation fault at this line.
commandArray[kk][ii - jj] = (char) input[ii];
this only happens after kk > 3 but runs well for all smaller numbers. Also the same problem occurs at kk >3 when i use different strings. with kk == 4 and (ii - jj) == 0.
it occurs when i want to fill an 2d array with characters.
//fill each Array entry with a command (a command is just a string)
jj = 0;
kk = 0;
ii = 0;
while (ii != (int) strlen(input)) {
commandArray[kk][ii - jj] = (char) input[ii];
if ((char) input[ii] == ';') {
commandArray[kk][ii - jj + 1] = '\0';
jj = ii + 1;
kk++;
}
ii++;
}
i am pretty sure that i have declared the 2d array correctly:
//allocate space for each command
commandArray = (char**) calloc(numberOfCommands, sizeof(char)); //create n char arrays
for (ii = 0; ii < numberOfCommands; ii++) {
commandArray[ii] = (char*) calloc((lengthOfCommand[ii]), sizeof(char));
}
i dont know f you need further code so i have used pastebin to include my complete code (~100 lines)
the Main that calls my function:
http://pastebin.com/P9TfDUs7
the complete Parser.c file:
http://pastebin.com/WFvrLS1r
and the Parser.h:
#ifndef PARSER_H_
#define PARSER_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void command(char* commandArray);
#endif /* PARSER_H_ */
Each command entry is a string of chars. When you allocate the memory for those strings (correctly, I think) you get back pointers to the first char in each string.
So your array of commands is implemented as a list of pointers. But when you allocated the memory for the list of pointers, you only allowed enough space for each pointer to fit in a char. It is highly unlikely that a pointer value, which is essentially a memory location, will fit in a char.
Try changing your first calloc call so that the second parameter is sizeof(char *).
If this is unclear, writing a tiny program to print out sizeof(char) and sizeof(char *) might help.
I would like to read from N text files (having similar structure: a few lines, each line having the same small number of words) and store in a string matrix the words read, in such a way that in each (row, col) position I have one word.
A simple (two lines, three words per line) specimen for the files is the following:
line1word1 line1word2 line1word3
line2word1 line2word2 line2word3
Delimiter for the words is space.
I have attempted this code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LENGTH 1000
#define MAX_TOKS 100
#define DELIMITERS " "
// line parsing utility
int parseString(char* line, char*** argv) {
char* buffer;
int argc;
buffer = (char*) malloc(strlen(line) * sizeof(char));
strcpy(buffer,line);
(*argv) = (char**) malloc(MAX_TOKS * sizeof(char**));
argc = 0;
(*argv)[argc++] = strtok(buffer, DELIMITERS);
while ((((*argv)[argc] = strtok(NULL, DELIMITERS)) != NULL) &&
(argc < MAX_TOKS)) ++argc;
return argc;
}
int main() {
char S[MAX_STRING_LENGTH];
char **A;
int n,i,j,l;
FILE *f;
char file[50];
char ***matrix;
matrix = malloc(MAX_TOKS * sizeof(char**));
//memory allocation for matrix
for (i = 0; i < MAX_TOKS; i++)
{
matrix[i] = malloc(MAX_TOKS * sizeof(char *));
for (j = 0; j < MAX_TOKS; j++)
{
matrix[i][j] = malloc(MAX_TOKS * sizeof(char));
}
}
int NFILE = 10; // number of files to be read
for(i=0;i<NFILE;i++)
{
sprintf(file,"file%d.txt",i);
f = fopen(file,"r");
l=0; // line-in-file index
while(fgets(S,sizeof(S),f)!=NULL) {
n = parseString(S,&A);
for(j=0;j<n;j++) {
matrix[i][l]=A[j];
printf("%s\t%s\n",matrix[i][l],A[j]);
}
l++;
}
fclose(f);
}
free(matrix);
free(A);
return(0);
}
The problem I can't solve is that there when checking for correspondance between the arrays (in order to be sure I am storing the single words correctly) using
printf("%s\t%s\n",matrix[i][l],A[j]);
I find that the last word (and only the last one) of each line, regardless of the file number, is not stored in matrix. That is to say, line1word1 and line1words of file0 are correctly stored in matrix[0][0][0] and matrix[0][0][1], but in the field matrix[0][0][2] there isn't line1word3, even if A[2] has it!
What am I doing wront? Any suggestion?
Many thanks in advance,
cheers
char ***matrix doesn't declare a three dimensional array. Your matrix would need to be something like char *matrix[a][b] to hold a two dimensional array of string pointers. In order to calculate addresses within an array, the compiler needs to know the all of dimensions but one. If you think about it, you will probably see why...
If you have two arrays:
1 2 3 1 2 3 4 5 6 7
4 5 6 8 9 10 11 12 13 14
7 8 9 15 16 17 18 19 20 21
You can see that item[1][1] is NOT the same item. Regardless of the dimensions in your array, the elements are typically arranged sequentially in memory, with each row following the previous (or possible column, depending on language, I suppose.) If you have an array of pointers, the actual content may be elsewhere, but the points would be arranged like this. So, in my examples above, you must provide the compiler with the number of columns so that it can find members (the number of rows can be variable.) In a three dimensional array, you must provide the first TWO dimensions so that the compiler may calculate item offsets.
I hope that helps.
EDIT: You can have truly dynamic array dimensions by creating your own function to process all array item accesses. The function would need to know the dynamic dimensions and the item index(s) so that it could calculate the appropriate address.
This looks wrong: buffer = (char*) malloc(strlen(line) * sizeof(char));
Firstly, there is no need to cast malloc in C. If your code doesn't compile without the cast, there are two possible reasons:
There is no prototype for malloc. Obviously this can cause problems, because no prototype means the function returns a default type: int, or an error occurs. This can cause your program to misbehave. To avoid this, #include <stdlib.h>.
You're using a C++ compiler. Stop. Either program in C++ (stop using malloc) or use a C compiler. If you want to use this project in a C++ project, compile your C code with a C compiler and link to it in your C++ compiler.
Secondly, sizeof(char) is always 1. There is no need to multiply by it.
Thirdly, a string is a sequence of characters ending at the first '\0'. This means a string always occupies at least 1 character, even if it is an empty string. What does strlen("") return? What is sizeof("")? You need to add 1 to make room for the '\0': buffer = malloc(strlen(line) + 1);.
This looks slightly wrong: (*argv) = (char**) malloc(MAX_TOKS * sizeof(char**));
malloc returns a pointer to an object. *argv is a char **, which means it points to a char *. However, in this case malloc returns a pointer to char ** objects. The representation isn't required to be identical. To avoid portability issues assosciated with this, follow this pattern variable = malloc(n * sizeof *variable); ... in this case, *argv = malloc(MAX_TOKS * **argv);
It gets more gritty as it goes. Forget everything you think you know about your code; Pretend you're going to come back to this in 24 months. What are you going to think of this?
argc = 0;
(*argv)[argc++] = strtok(buffer, DELIMITERS);
while ((((*argv)[argc] = strtok(NULL, DELIMITERS)) != NULL) &&
(argc < MAX_TOKS)) ++argc;
There's actually an off-by-one here, too. Assuming argc == MAX_TOKS, your loop would attempt to assign to (*argv)[MAX_TOKS]. This loop is where I believe your problem lies, and the solution is to express your intent more clearly rather than attempting to cram as much code into one line as possible. How would you rewrite this? Here's what I'd do, in this situation:
char *arg;
size_t argc = 0;
do {
arg = strtok(buffer, DELIMITERS);
buffer = NULL;
(*argv)[argc] = arg;
argc++;
} while (argc < MAX_TOKS && arg != NULL);
The problem is that your parsing loop doesn't increment when strtok returns NULL. Hence, your function returns the position of the last item. Supposing you had two tokens, your parsing function would return 1. Your display loop displays items up to, but not including this position: for(j=0;j<n;j++). You could use the suggested improvement, or change your loop: for (j = 0; j <= n; j++). Either way, you'll need to fix those off-by-ones.
Out of curiosity, which book are you reading?
so I'm using C, I cant seem to get this to work right. It's an array of pointers to structs which contain some contact info. I can't seem to get the qsort to sort correctly.
Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
#define ELEMENTS 50
int sortZips(const void *a, const void *b);
typedef struct contactInfo {
char name[MAX];
char street[MAX];
char cityState[MAX];
char zipCode[MAX];
} contacts;
int main() {
int i = 0;
contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));
/* allocate array */
for (i = 0; i < ELEMENTS; i++) {
contactArray[i] = malloc(sizeof(contacts));
}
/* populate array */
for (i = 0; i < ELEMENTS; i++) {
fgets(contactArray[i]->name,MAX,stdin);
fgets(contactArray[i]->street,MAX,stdin);
fgets(contactArray[i]->cityState,MAX,stdin);
fgets(contactArray[i]->zipCode,MAX,stdin);
printf("%s", contactArray[i]->name);
printf("%s", contactArray[i]->street);
printf("%s", contactArray[i]->cityState);
printf("%s", contactArray[i]->zipCode);
}
printf("\n");
/* qsort((void *)contactArray, ELEMENTS, sizeof(contacts *), sortZips); */
for (i = 0; i < ELEMENTS; i++) {
fputs(contactArray[i]->name,stdout);
fputs(contactArray[i]->street,stdout);
fputs(contactArray[i]->cityState,stdout);
fputs(contactArray[i]->zipCode,stdout);
}
}
/* sortZips() sort function for qsort */
int sortZips(const void *a, const void *b) {
const contacts *ia = *(contacts **)a;
const contacts *ib = *(contacts **)b;
return strcmp(ia->zipCode, ib->zipCode);
}
The output is printing the addresses (I have 50 in an input file) and then some random characters, like a huge block of them, then the sorted list after that which is messed up and not sorted right.
Please any help would be appreciated. I need to learn what's wrong here and why.
Thanx.
First rule: always check input functions - in this case, fgets(). You don't know whether everything is working correctly or not if you do not check.
Second: use enum in preference to #define in general.
With the check for early EOF in place, your code sorted my sample data (6 rows) cleanly. It also compiled cleanly - which is very unusual (that's a compliment; I use stringent warnings and even my code seldom compiles cleanly the first time). My amended version of your code is very similar to yours:
int main(void)
{
int i = 0;
int num;
contacts **contactArray = malloc(ELEMENTS * sizeof(contacts *));
/* allocate array */
for (i = 0; i < ELEMENTS; i++)
contactArray[i] = malloc(sizeof(contacts));
/* populate array */
for (i = 0; i < ELEMENTS; i++)
{
if (fgets(contactArray[i]->name,MAX,stdin) == 0 ||
fgets(contactArray[i]->street,MAX,stdin) == 0 ||
fgets(contactArray[i]->cityState,MAX,stdin) == 0 ||
fgets(contactArray[i]->zipCode,MAX,stdin) == 0)
break;
printf("%s", contactArray[i]->name);
printf("%s", contactArray[i]->street);
printf("%s", contactArray[i]->cityState);
printf("%s", contactArray[i]->zipCode);
}
printf("\n");
num = i;
qsort(contactArray, num, sizeof(contacts *), sortZips);
for (i = 0; i < num; i++)
{
fputs(contactArray[i]->name,stdout);
fputs(contactArray[i]->street,stdout);
fputs(contactArray[i]->cityState,stdout);
fputs(contactArray[i]->zipCode,stdout);
}
return 0;
}
The data I used was trivial repetitions of sets of 4 lines like this:
First LastName7
7 Some Street
City, CA
95437
Note that the 'error checking' I do in the input is the bare minimum that 'works'. If you get an over-long line in the input, one field will not contain a newline, and the next will contain the next section of the input line (possibly all the rest, possibly not - it depends on how badly overlong the line is).
If your addresses are printing out rubbish at the end, then it's almost certainly because you haven't allocated enough space for them. Twenty characters is a little on the low side for addresses.
What's probably happening is that you have an address like:
14237 Verylongstreetname Avenue
and, when you do fgets (street,20,stdin);, only 14237 Verylongstree will be read (19 characters, leaving space for the null terminator).
And, here's the crux: the file pointer will still be pointing at the tname Avenue bit so that, when you try to read the cityState, you'll get that. And, when you try to read the zipCode, you'll get the cityState line, effectively stuffing up your sorting.
I believe that you have enough space. Because you are using fgets and your size of MAX, the strings should be cut to fit and have a terminating NUL at the end.
Two things that might be messing it up:
fgets will read from where it stopped reading if the line is too long. That will result in an address of "This is too long so", " it will be cut\n". And then the rest of the input will be all over the place.
If you do not have enough input to fill ELEMENTS items then you'll get whatever random data was in the malloc'd memory. If you were to use calloc instead, it would zero the memory for you. Although the better idea would be to use a counter of how many items were actually read, instead of assuming there will be ELEMENTS items.