Im trying to make a simple encryption program, nothing mathematical or so but to go further I need to know what causes the segmentation fault in my program. I have tried to simplify my code..
char *
createAlfabeth(void)
{
char * alfa = NULL;
strcpy(alfa, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
int i, j=1, k=0;
for(i=0; i<(sizeof(alfa)/sizeof(char)); i++, j+=3)
{
if(j>25)
{
j=1+(k++);
}
swap(alfa, i, j);
}
return alfa;
}
char *
codificator(char *mess, const char *alfa)
{
int key[]=PRIVATE_KEY;
char *newmess=NULL;
int i, j;
for(i=0, j=0; mess[i]!='\0'; i++, j++)
{
if(j>(sizeof(key)/sizeof(key[0])))
{
j=0;
}
newmess[i]=alfa[i+key[j]];
}
return newmess;
}
int
main(void)
{
char *alfa=crearAlfabeto();
printf("write your message :\n");
char message[20];
scanf("%s", message);
char *codified=codificator(message, alfa);
printf("The codified message is: %s \n", codified);
return 0;
}
SOLVED: POST MEMORANDUM
I solved the problem with the recommendations by ouah and askmish below (thanks to both). And for you people googling to this answer, I want to say that this problem has to do with the heap handling. As I did not store enough space for the strings that I declared later or initialized there was not enough memory allocated to them.
This is was the malloc, realloc, calloc (and free) functions purpose is to handle. The segmentation fault comes from that I tried to move beyond the allocated memory for the data segment in the code. Every program allocated memory for the code (code segment), and data (data segment) and by not telling explicitly in c how much you are going to store in data segment you get this error. This is my understanding of what I have read, if someone with more insight wants to comment on this please do..
char * alfa = NULL;
strcpy(alfa, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
You need to allocate memory for your array object.
For example:
char *alfa = malloc(sizeof "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
/* check that malloc succeeds here */
strcpy(alfa, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
In addition to ouah's answer:
Instead of this in codificator:
char *newmess=NULL;
int i, j;
for(i=0, j=0; mess[i]!='\0'; i++, j++)
{
if(j>(sizeof(key)/sizeof(key[0])))
{
j=0;
}
newmess[i]=alfa[i+key[j]];
}
Write this:
char *newmess=NULL;
int i, j;
newmess = malloc(strlen(mess)*sizeof(char)); //This line could be written in many ways
if(newmess != NULL) //Handle memory allocation failing.
{
for(i=0, j=0; mess[i]!='\0'; i++, j++)
{
if(j>(sizeof(key)/sizeof(key[0])))
{
j=0;
}
newmess[i]=alfa[i+key[j]];
}
}
Please ensure you allocate memory to the pointers before using them with strings.Else you will get Seg Faults.
You have to use the fix of both mine and ouah's to remove the segmentation faults.
Related
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 1 year ago.
This code is to make and print a matrix out but i am not sure why i am getting seg fault, it is because I am not freeing memory, if so how would i free it?
void printMatrix(struct Matrix *M){
struct Matrix *temp = M;
for(int i=0; i< temp->rows;i++){
for(int j=0; j< temp->cols;j++){
printf("%.f",getVal(temp,i,j));
}
printf("\n");
}
}
void makeMatrix(struct Matrix *M, int row, int col, int num){
M = malloc(sizeof(struct Matrix));
M->rows=row;
M->cols=col;
M->m =malloc(100*sizeof(double)*M->rows*M->cols);
for(int i=0; i<M->rows;i++){
for(int j=0; j<M->cols;j++){
setVal(M,i,j,num);
}
}
free(M);
}
int main(int argc, char const *argv[]) {
struct Matrix *test;
makeMatrix(test,10,10,10);
printMatrix(test);
return 0;
}
Your makeMatrix function is wrong. Parameter M is a local variable when makeMatrix executed. Thereofre any changes to M are not visible when the function ends. As result test is not initialized when passed to printMatrix causing failure then the pointer is dereferenced.
The solution is returning M from the function by value.
struct Matrix *makeMatrix(int row, int col, int num){
struct Matrix *M = malloc(sizeof(struct Matrix));
if (!M) return NULL;
M->rows=row;
M->cols=col;
M->m =malloc(100*sizeof(double)*M->rows*M->cols);
if (!M->m) {
free(M);
return NULL;
}
for(int i=0; i<M->rows;i++){
for(int j=0; j<M->cols;j++){
setVal(M,i,j,num);
}
}
return M;
}
Usage:
struct Matrix *test = makeMatrix(10,10,10);
Moreover, malloc(100*sizeof(double)*M->rows*M->cols); looks a bit wasteful because it consumes 100x more memory than needed. I'm pretty sure that malloc(sizeof(double)*M->rows*M->cols); would suffice.
First, always have to check if the malloc successfully allocates memory. So after the first call to malloc, you should write something like that:
if(!M)
{
printf("malloc failed to allocate memory for M");
return;
}
and so on. Also you should free each memory space you allocated with malloc. In your case you should also free(M->m)
I have a problem with free.
I test my code in online compiler but everything is OK. However in my device (which is a POS) it rises exception when calling free. It frees two of 4 variables and then rise exception.
My real Code for device:
char **MenuItems = malloc (MAX_PACKETS * sizeof(char *));
struct packetInfos * packets = (struct packetInfos *)malloc(sizeof(struct packetInfos)*MAX_PACKETS);
size = getPacketNames(groupId,packets,MenuItems);
...
...
...
TRACE(("====size %d",size));
for(;i<size;i++) {
TRACE(("====%d=",i,MenuItems[i]));
free(MenuItems[i]);
}
free(MenuItems);
gives me:
[src/menu.c][NetChargeMenu_L3][1637]>>>====size 4
[src/menu.c][NetChargeMenu_L3][1639]>>>===counter=0 address=34259480
[src/menu.c][NetChargeMenu_L3][1639]>>>===counter=1 address=34260528
Sometimes it frees all variables but give me the following error and freeze everything:
Error in `<unknown>': corrupted double-linked list: 0x011eb8e0
my program is something like this
#include <stdio.h>
#include <stdlib.h>
#define MAX 16
int getPacketNames(char **names){
int limit = 4;
int i = 0;
for(i=0;i<MAX;i++) {
if(i==limit)
break;
names[i] = malloc(64);
sprintf(names[i],"random text %d",i);
}
return i;
}
int main()
{
printf("Hello World");
int i=0;
int size=0;
char **MenuItems = malloc (MAX * sizeof(char *));
size = getPacketNames(MenuItems);
// do something
for(i=0;i<size;i++) {
free(MenuItems[i]);
}
free(MenuItems);
return 0;
}
I read this post (What does 'corrupted double-linked list' mean) by cannot find a useful hint for my code in C.
Thanks for any hints.
The cause is for malloc memory not for free it. I used fixed length in allocation! Before I used dynamic size for allocating. However allocating dynamic size memory must not be a problem, but using fixed size allocation maybe solve other problems such my problem.
My previous code (With problem when free):
struct packetInfos{
int id;
char name[64];
long amount;
};
void getOperatorNames(char *names[]) {
int i=0;
for(; i<MAX; i++) {
sprintf(packets[i].name, "%s", sqlite3_column_text(stmt, 2));
names[i] = malloc(strlen(packets[i].name) + 1); // the cause of problem in free
strcpy(names[i], op[i].fname);
}
}
My current code (Without problem):
void getOperatorNames(char *names[]) {
int i=0;
for(; i<MAX; i++) {
sprintf(packets[i].name, "%s", sqlite3_column_text(stmt, 2));
names[i] = malloc(64);
strcpy(names[i], op[i].fname);
}
}
This code keeps saying segmentation fault.
for(i=0; i<(numTopps-1); i++)
{
if(kcalTopp[i]<kcalTopp[i+1])
{
temp=*kcalTopp[i];
*kcalTopp[i]=*kcalTopp[i+1];
*kcalTopp[i+1]=temp;
}
}
I think above part is a problem.
but I can't figure what is the problem
#include <stdio.h>
#include <stdlib.h>
void sort(int *kcalTopp[], int numTopps);
int main(void)
{
int numTopps, doughPrice, eachToppPrice, kcalDough, i, j, totalKcal, highest, kcalperDol;
scanf("%d %d %d %d", &numTopps, &doughPrice, &eachToppPrice, &kcalDough);
int *kcalTopp;
kcalTopp=(int*)malloc(sizeof(int)*numTopps);
for(i=0; i<numTopps; i++)
{
scanf("%d", &kcalTopp[i]);
}
totalKcal=kcalDough;
highest=totalKcal/doughPrice;
sort(&kcalTopp, numTopps);
for(i=0; i<numTopps; i++)
{
for(j=0; j<=i; j++)
{
totalKcal=totalKcal+kcalTopp[j];
kcalperDol=totalKcal/(doughPrice+i*eachToppPrice);
if(kcalperDol>highest)
{
highest=kcalperDol;
}
}
}
printf("%d", highest);
return 0;
}
void sort(int *kcalTopp[], int numTopps)
{
int temp, i;
for(i=0; i<(numTopps-1); i++)
{
if(kcalTopp[i]<kcalTopp[i+1])
{
temp=*kcalTopp[i];
*kcalTopp[i]=*kcalTopp[i+1];
*kcalTopp[i+1]=temp;
}
}
}
Indeed, your problem is the sort function you described, as you suspected. Are you aware what *kcalTopp[i]=*kcalTopp[i+1]; does exactly? You get as parameter an int *array[] which is equivalent to int **array (you can see it as an array of arrays of ints). So when you tell C to access array[i] you will access the i-th array. This is a pointer, and in fact *kcalTopp[i] will be the first element from the i-th array. What you are doing here is swapping first elements from the arrays, but in practice you have a single array of ints (or more technically, an array of length 1 of arrays). The simplest fix is to write:
temp=(*kcalTopp)[i];
(*kcalTopp)[i]=(*kcalTopp)[i+1];
(*kcalTopp)[i+1]=temp;
just to change the precedence of the operators. Now, what we achieved is: we take the first array from the array list (it's the only one we have, isn't it?) with (*kcalTopp); this is an int *, not int ** anymore. Now you can safely access the i-th element from it.
Without parentheses, you would first access the i-th array, because in *kcalTopp[i], the [i] part will execute before the * part.
Anyway, to simplify things, you are not required to take as parameter an int *kcalTopp[], you can simply take int kcalTop[] or int *kcalTopp and not use * anymore:
temp = kcalTopp[i];
kcalTopp[i] = kcalTopp[i+1];
kcalTopp[i+1] = temp;
The original code in your post is using an extra (unnecessary) layer of indirection for kcalTopp, resulting in attempts to manipulate an array of addresses (pointers) as opposed to manipulating int values pointed to in memory. This in turn is likely to be the reason you are seeing segmentation faults, which occur when attempting to access memory that you do not own. For some input values, and depending on what day you run your program, it may run, and it may crash.
(This is sometimes referred to as undefined behavior, and is the reason that the problem will not always manifest itself, making you think your program is flawless, when it is not.)
The following contains edits to your original code for the purpose of illustrating some of the suggestions in comments. (not to fix every logic error.) The edits do include treating kcalTopp as a pointer to int memory as opposed to an array of int *. See in-line comments for clarifications:
//void sort(int *kcalTopp[], int numTopps);//*kcalTopp[] is an array of pointers
void sort(int *kcalTopp, int numTopps);//*kcalTopp is a pointer to 'int' memory
int main(int argc, char *argv[])
{
int numTopps, doughPrice, eachToppPrice, kcalDough, i, j, totalKcal, highest, kcalperDol;
//scanf("%d %d %d %d", &numTopps, &doughPrice, &eachToppPrice, &kcalDough);
if(argv != 5) //simple reading in of command line args
{
printf("4 input values required. Exiting");
return 0;
}
//note, each of these calls includes simple for test for success before going on
numTopps = strtol(argv[1], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[1] Bad input, exiting"); return 0;}
doughPrice = strtol(argv[2], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[2] Bad input, exiting"); return 0;}
eachToppPrice = strtol(argv[3], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[3] Bad input, exiting"); return 0;}
kcalDough = strtol(argv[4], (char **) NULL, 10);
if(errno == ERANGE) {printf("argv[4] Bad input, exiting"); return 0;}
int *kcalTopp;
//This statement (without cast) is sufficient to create memory for kcalTopp
kcalTopp = malloc(sizeof(int)*numTopps);
if(!kcalTopp)//should always test before using memory
{
printf("memory allocation failed, exiting");
return 0;
}
for(i=0; i<numTopps; i++)
{
scanf("%d", &kcalTopp[i]);
}
totalKcal=kcalDough;
highest=totalKcal/doughPrice;
//sort(&kcalTopp, numTopps);
// ^ not needed
sort(kcalTopp, numTopps);
for(i=0; i<numTopps; i++)
{
for(j=0; j<=i; j++)
{
totalKcal=totalKcal+kcalTopp[j];
kcalperDol=totalKcal/(doughPrice+i*eachToppPrice);
if(kcalperDol>highest)
{
highest=kcalperDol;
}
}
}
printf("%d", highest);
return 0;
}
void sort(int *kcalTopp, int numTopps)//note removal of []
{
int temp, i;
for(i=0; i<(numTopps-1); i++)
{
if(kcalTopp[i]<kcalTopp[i+1])
{
temp=kcalTopp[i];//note removal of '*' from all kcalTopp
kcalTopp[i]=kcalTopp[i+1];
kcalTopp[i+1]=temp;
}
}
}
I am getting segmentation fault in C and I have no idea what is the reason. As far as I know segmentation fault occurs when system run our of memory. I checked my loops and they seem to have clear termination conditions. Thus, I am confused what causes my code to crash. As I checked this fault should occurs in mygetline or readlines functions.
Is there any debugger that I can use to find our why program crashes?
#include <stdio.h>
#include <string.h>
#define MAXLINE 100
#define MAXLINENUM 10
int readlines(char *lines[]);
int mygetline(char line[]); /* getline: read a line into s, returns length */
void writelines(char *lines[], int nlines);
int main()
{
int i = 0;
char *lines[MAXLINE];
i = readlines(lines);
writelines(lines, i);
return 0;
}
int mygetline(char line[]){
int i, c;
for(i = 0; i < MAXLINE-1 && (c = getchar()) != '\n' && c != EOF; i++){
line[i] = c;
}
line[i] = '\0';
return i;
}
int readlines(char *lines[]){
int i, c;
i = 0;
while((c = mygetline(lines++)) > 0 && i < MAXLINENUM){ //line[i]
i++;
}
lines[--i] = '\0';
return i;
}
void writelines(char *lineptr[], int nlines) {
int i;
for (i = 0; i < nlines; i++)
printf("%s\n", lineptr[i]);
}
The reason for the segmentation fault is that you don't allocate any storage for the strings. You declare an array of char* here:
char *lines[MAXLINE];
But nowhere do you ever allocate memory to hold the actual strings.
To continue using an array of char*, allocated that way, you'd need to use malloc to allocate memory for the actual strings.
lines[i] = malloc(...);
Obviously you'll need to:
Decide how much memory to allocate for each string.
Call free to dispose of the memory when you are done with it.
Add some code to check that you don't write beyond the end of any of your buffers.
You created an array char *lines[MAXLINE] which is an array of pointers. However, you've not initialized those pointers, so they're pointing to garbage. You then pass the garbage pointer into mygetline which writes to the garbage pointer, and this is the problem.
Not only do you need to allocate memory for the line to be stores in, but you also need to get mygetline how many characters it can read. If you allocate space for 10 characters, but the user enters 20 you're going to have a similar problem.
The reason that you get a segfault is that your code reads the data into lines without allocating any memory for the characters that you read.
Your main allocates memory for the pointers to strings, but it does not initialize these pointers. You need to add code to set these pointers to valid blocks of memory, for example, by allocating some max number of characters with malloc:
while(i < MAXLINENUM) {
lines[i] = malloc(MAXLINE);
if (!mygetline(lines[i++])) {
break;
}
}
Also note that you confused MAXLINE with MAXLINENUM in the declaration of lines.
The reason for the segmentation fault is the memory allocation.
You can not allocate memory like char *lines[MAXLINE];.
Try the following code
If you are Using 1D array
char *lines;
lines=(char *)malloc(MAXLINE*sizeof(char));
If you are using 2D array go with this code
char **lines;
lines=(char **)malloc(MAXLINENUM*sizeof(char *));
for(i=0;i<MAXLINENUM;i++)
lines[i]=(char *)malloc(MAXLINE*sizeof(char));
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int queensonboard(int n,int m)
{
int count=0,i,j,flag,x[100];
char **board;
/* board= (char**)calloc(sizeof(char*),n);
for(i=0;i<n;i++)
{
board[i]= (char*)calloc(sizeof(char),m);
}
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%c",&board[i][j]);
}
}*/
// x==(int*)calloc(sizeof(int),n);
flag=0;
for(i=0;i<n;i++)
{
x[i]=0;
}
while(i>0)
{
while(x[i]<m)
{
x[i]++;
// if(board[i][x[i]]!='#')
// {
for(j=0;j<i;j++)
{
if(x[j]==x[i])
{
flag=1;
}
else if(x[j]-x[i]==abs(j-i))
{
flag=1;
}
else
{
flag=0;
}
}
if(flag==0 && i==n-1)
{
count++;
}
else if(flag==0)
{
i++;
}
//}
}
x[i]=-1;
i--;
}
printf("%d\n",count);
}
int main() {
int i,n,m,j;
scanf("%d",&i);
for(j=1;j<=i;j++)
{
scanf("%d %d",&n,&m);
queensonboard(n,m);
}
return 0;
}
This is the code. The program gives segmentation fault on dynamically allocating any of the arrays x or board.(Commented here.)
That is when i try to allocate with calloc.
Couldnt really figure out why this is happening. Tried changing thins and that but still happening.
The definition of calloc is as follows:
void *calloc(size_t num, size_t size);
num Number of elements to allocate.
size Size of each element.
You have your arguments swapped. It should be like this:
board = calloc(n, sizeof(char *));
for(i = 0; i < n; i++)
{
board[i]= calloc(m, sizeof(char));
}
Also, this line is incorrect:
x == (int*)calloc(sizeof(int), n);
This, is comparing the address of x to the address that calloc returns. The logic is incorrect too. The way you have x defined, it is an array of 100 ints.
If you want an array of int pointers, you need to do this:
int *x[100];
If you want a pointer to array of 100 ints, you need to do this:
int (*x)[100];
If you're simply trying to allocate memory for x, you've already accomplished that with your declaration:
int x[100];
The obvious explanation for a segmentation fault is that you are de-referencing an invalid pointer. The obvious way for that to happen would be for any of the calls to calloc to return NULL. And calloc does that when it fails. You are not checking the return value of calloc for errors and I think it very likely that one of the calls returns NULL because you supplied invalid parameters.
So, debug the problem by checking the return value of the calls to calloc, and checking the input parameters that you pass. I know it's frustrating to have to do this, but you must check for errors in all user input, and you must check the return values of all calls to memory allocation functions.
This line
x==(int*)calloc(sizeof(int),n)
where you perform comparison rather than assignment is also clearly problematic. You meant:
int *x = calloc(n, sizeof(int));
And yes, you have the arguments to calloc swapped as others point out. You should certainly fix that but I do not believe that to be the cause of your problem.