Bus error and Segmentation fault depending on value inputted - c

I'm having trouble with my code and hope you could help. When I input an odd number I'm given a segmentation fault, and a bus error if it's even. I'm trying to add 00's to a data array to bring it from length Nprime to a new, larger length Ndprime that I input. I'm doing this in a function *fpad, where my paddata array contains Nprime complex numbers (i.e. 2*Nprime components), and needs to be brought up to size 2*Ndprime.
double *fpad(double *paddata, unsigned int Nprime, unsigned int Ndprime)
{
if (Nprime!=Ndprime)
{
paddata=(double*)realloc(paddata,(sizeof(double)*((2*Ndprime)-1)));
for(i>=((2*Nprime));i<(2*Ndprime);i++) paddata[i]=0;
if(paddata==NULL) /* Checks memory is reallocated */
{
printf("\nError reallocating memory.\n");
free(paddata);
exit(EXIT_FAILURE);
}
}
return(paddata);
}
ANy help would be appreciated, I can't see what I'm doing wrong.

You are using an undeclared variable i (or maybe it is a global).
for(i>=((2*Nprime));i<(2*Ndprime);i++) paddata[i]=0;
Your first condition checks whether i is smaller than or larger than 2*Nprime (but does not set i). It then goes around accessing the array using this not-properly-initialized value of i that could be negative, which would lead to problems.
You only check whether the memory reallocation succeeded after the loop diagnosed as problematic above. If the memory allocation fails, you've carefully zapped the original copy of the pointer in this function. There is no point in freeing the null pointer — but since you exit on allocation failure, there isn't too much of a problem.
Put your initialization loop after the memory check, with slightly less exuberance in the number of parentheses:
for (int i = 2*Nprime; i < 2*Ndprime; i++) // C99 (and C++)
paddata[i] = 0.0;
If you can't use C99 notation, declare int i; in the function.
Don't create global variables called i, ever.
Do pay attention to your compiler's warnings. If it wasn't warning you about 'statement with no effect', you haven't turned on enough warnings.

I recommend the function memset function to init your dynamic array.I think the index 'i' in the 'for' statement should range from 0 to 2*Ndprime-2.

Related

What does this C program terminate as soon as it takes a input?

This is my first question here, so I apologize in advance.
Whenever it executes it just takes one number as input and then terminates.
Can't, we use this logic to find out the greatest and smallest number among any numbers??
#include<stdio.h>
void main()
{
int *p,n,i,max,min;
printf("How many numbers?= ");
scanf("%d",&n);
printf("\nStart entering numbers\n");
for(i=0;i<n;i++){
scanf("%d",(p+i));
}
max=*(p+0);
for(i=0;i<n;i++)
{
if(*(p+i)>max)
{max=*(p+i);}
}
printf("Maximum number = %d\n",max);
min=*(p+0);
for(i=0;i<n;i++)
{
if(*(p+i)<min)
min=*(p+i);
}
printf("Minimum number = %d",min);
}
Whenever it executes, it just takes one number as input and then terminates.
Can't,we use this logic to find out the greatest and smallest number among any numbers?
In your code you have a pointer to a int called p that points to nothing, it is empty.
Then you call scanf() and read into the empty pointer p.
scanf("%d",(p+i));
This will not work since p points to nothing and when scanf() tries to store something inside it, it will most likely lead to a segmentation fault or undefined behaviour.
To fix it you could allocate memory for p with malloc():
int *p = malloc(sizeof(int) * n);
if (p == NULL)
{
fprintf(stderr, "malloc failed");
// error procedure
}
This will create an array capable of storing n elements of type int.
Notes:
Your code uses a lot of *(p+i)s, this could cause confusion and lead to error prone code, it is best that you use p[i] instead.
Your main function has return type void, instead you should use int so you can return a error code of some sort if something fails.
You should test the return value of scanf to see if it failed to read something from the user.
You have undefined behaviour here: You're declaring a pointer p and start assigning values not only to the memory location of p but also of subsequent pointers p+1, p+2 etc. But you've never checked if the system allocated available memory to you. You may be lucky and get a pointer to a memory address that has sufficient contiguous memory available to hold all the values that follow, but you can't rely on that.
A better way would be:
int n,i,max,min;
if (!(scanf("%d",&n))) return;
printf("\nStart entering numbers\n");
int *p = malloc(sizeof(int)*n);
if (p == NULL) return;
Essentially, you want to use malloc() (for which you will have to #include <stdlib.h> to allocate as much memory as you need for the numbers. For good practice, you also want to check whether the scanf and the malloc worked out right, which is the job of the two if statements that terminate the program in case something went wrong. If not, you can be sure to have the memory you need, and the program can go on.
In terms of notation, you can use *(p+1) etc if you want to, but it's more common (and more readable) to use p[1], and in fact the C standard requires the two to be equivalent.
If the number of p members is very small, I (personally) wouldn't do the job with malloc(), and then (one souldn't forget!) free();
I would just do something like
int p[100];
instead of *p, and to refer like p[0] or p[i] to them instead of using pointers.

Dynamic array without malloc?

I was reading through some source code and found a functionality that basically allows you to use an array as a linked list? The code works as follows:
#include <stdio.h>
int
main (void)
{
int *s;
for (int i = 0; i < 10; i++)
{
s[i] = i;
}
for (int i = 0; i < 10; i++)
{
printf ("%d\n", s[i]);
}
return 0;
}
I understand that s points to the beginning of an array in this case, but the size of the array was never defined. Why does this work and what are the limitations of it? Memory corruption, etc.
Why does this work
It does not, it appears to work (which is actually bad luck).
and what are the limitations of it? Memory corruption, etc.
Undefined behavior.
Keep in mind: In your program whatever memory location you try to use, it must be defined. Either you have to make use of compile-time allocation (scalar variable definitions, for example), or, for pointer types, you need to either make them point to some valid memory (address of a previously defined variable) or, allocate memory at run-time (using allocator functions). Using any arbitrary memory location, which is indeterminate, is invalid and will cause UB.
I understand that s points to the beginning of an array in this case
No the pointer has automatic storage duration and was not initialized
int *s;
So it has an indeterminate value and points nowhere.
but the size of the array was never defined
There is neither array declared or defined in the program.
Why does this work and what are the limitations of it?
It works by chance. That is it produced the expected result when you run it. But actually the program has undefined behavior.
As I have pointed out first on the comments, what you are doing does not work, it seems to work, but it is in fact undefined behaviour.
In computer programming, undefined behavior (UB) is the result of
executing a program whose behavior is prescribed to be unpredictable,
in the language specification to which the computer code adheres.
Hence, it might "work" sometimes, and sometimes not. Consequently, one should never rely on such behaviour.
If it would be that easy to allocate a dynamic array in C what would one use malloc?! Try it out with a bigger value than 10 to increase the likelihood of leading to a segmentation fault.
Look into the SO Thread to see the how to properly allocation and array in C.

Using long int as a parameter for malloc

int main() {
int n;
long u=0,d=0,count=0,i=0;
char *p=(char *)malloc(sizeof(char)*n);
scanf("%ld",&n);
scanf("%s",p);
for(i=0;i<n;i++){
if(p[i]=='U'){
u=u+1;
}
if(p[i]=='D'){
d=d+1;
}
if((d-u)==0 && p[i]=='U'){
count=count+1;}
}
printf("%ld",count);
return 0;
}
In this standard syntax for implicit memory allocation, if i replace "int n;" with "long int n;"
An error pops up saying:
GDB trace:
Reading symbols from solution...done.
[New LWP 10056]
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
I have searched everywhere for a solution, rather i quite dont know what to search for,
i would be greatful if anyone helps me out. Thanks :)
(This was executed on an online compiler)
There are a couple of things that I would like to point out:
First of all, you do not have to declare n as "long int". "long int" and "long" are the same. So,
long int n; //is same as
long n;
malloc() works perfectly fine whether n is an "int" or a "long". However, you don't seem to have initialized n. What is the value of n? C does not perform auto-initialization of variables and n might have a garbage value (even negative) which might cause your program to crash. So please give a value to n.
long n = 10; //example
or use a scanf() to input a value.
Now in your code, what is scanf() doing "after" malloc? I presume that you intended to read a value for n and then pass it to malloc. So please change the order of code to this:
scanf("%ld",&n);
char *p=(char *)malloc(sizeof(char)*n);
I ran your program with these changes on my system and it works fine (no segmentation fault)
malloc() limits: We know that malloc allocates from a heap. But I really don't see malloc returning NULL on current platforms (which are generally 64 bit). However, if you do try to allocate a very large chunk of memory, malloc might return NULL which will cause your program to crash.
So it's good to check the return value for malloc() and if that's NULL then take appropriate actions (such as retry or exit the program)
Having a check like the one below will always help:
if (p == NULL) {
printf("Malloc error");
exit(1);
}
Extracting the relevant parts of your code:
int n;
char *p=(char *)malloc(sizeof(char)*n);
The parameter to malloc is of type size_t, which is an unsigned type. If you pass an argument of any other integer type, it will be implicitly converted to size_t.
You report that with int n; you don't see a problem, but with long int n; your program dies with a segmentation fault.
In either case, you're passing an uninitialized value to malloc(). Just referring to the value of an uninitialized object has undefined behavior.
It may be that the arbitrary long int value you're passing to malloc() happens to cause it to fail and return a null pointer, causing a segmentation fault later when you try to dereference the pointer; the arbitrary int value might just happen to cause malloc to succeed. Checking whether malloc succeeded or failed would likely avoid the segmentation fault.
Passing an uninitialized value to malloc() is a completely useless thing to do. The fact that it behaves differently depending on whether that uninitialized value is an int or a long int is not particularly significant.
If you're curious, you might add a line to print the value of n before calling malloc(), and you definitely should check whether malloc() reported failure by returning a null pointer. Beyond that, you know the code is incorrect. Don't waste too much time figuring out the details of how it fails (or, worse, why it sometimes doesn't fail). Just fix the code by initializing n to the number of bytes you actually want to allocate. (And define n as an object of type size_t.)
Some more points:
The code in your question is missing several required #include directives. If they're missing in your actual code, you should add them. If they're present in your actual code, you should have included them in your question. Don't make assumptions about what you can safely leave out.
int main() should be int main(void). (This is a minor point that probably doesn't make any practical difference.)
scanf("%s",p);
This is inherently dangerous. It reads a blank-delimited string that can be arbitrarily long. If the user enters more characters than the buffer p points to can hold, you have undefined behavior.
u=u+1;
Not incorrect, but more idiomatically written as u ++;.
(d-u)==0 is more clearly and safely written as d == u. (For extreme values of d and u the subtraction can overflow; an equality comparison doesn't have that problem.)

Not receiving a seg fault when expected

I'm in the process of learning how to use pointers and structs in C. Naturally, I'm trying to deliberately break my code to further understand how the language works. Here is some test code that works as I expected it to work:
#include <stdio.h>
#include <stdlib.h>
struct pair {
int x;
int y;
};
typedef struct pair pair;
void p_struct( pair ); //prototype
int main( int argc, char** argv ) {
pair *s_pair;
int size, i;
printf( "Enter the number of pair to make: " );
scanf( "%d", &size );
getchar();
printf( "\n" );
s_pair = (pair*)malloc( size * sizeof(pair) );
for( i = 0; i < size; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
getchar();
return (EXIT_SUCCESS);
}
void p_struct( pair s_pair ) {
printf( "\n%d %d\n", s_pair.x, s_pair.y );
}
As previously stated, this code is functional as far as I can tell.
I then decided to modify a part of the code like so:
for( i = 0; i < size + 3; i++ ) {
s_pair[i].x = i;
s_pair[i].y = i;
p_struct( s_pair[i] );
}
This modification did not produce the seg fault error that I expected it would. All of the "pairs" were printed despite me exceeding the buffer I explicitly set when assigning a value to my variable size using the scanf function.
As I understand pointers (correct me if I'm wrong), a contiguous block of memory of size size*sizeof(pair) is reserved by the memory manager in the heap when I called the malloc function for my pointer of type pair s_pair. What I did was I exceeded the last assigned address of memory when I modified my for loop to the condition i < size + 3.
If I'm understanding this correctly, did my pointer exceed its reserved memory limit and just so happen to be in the clear because nothing adjacent and to the right of it was occupied by other data? Is this normal behaviour when overflowing a buffer?
To add, I did receive a seg fault when I tested with a for loop condition of i < size + 15. The thing is, it still prints the output. As in, it prints the pair "0 0" to pair "24 24" when size = 10 on the screen as per the p_struct function I made. The program crashes by seg fault only after it gets to one of those getchar()s at the bottom. How on earth could my program assign values to pairs that exceed the buffer, print them on the screen, and then all of a sudden decide to crash on seg fault when it gets to getchar()? It seemed to have no issue with i < size + 3 (despite it still being wrong).
For the record, I also tested this behaviour with a regular pointer array:
int size, i, *ptr;
scanf( "%d", &size );
ptr = (int*)malloc( size * sizeof(int) );
for( i = 0; i < size + 15; i++ )
ptr[i] = i;
This produces the exact same result as above. At i < size + 3 there doesn't seem to be any issue with seg faults.
Finally, I tested with an array, too:
int i, array[10];
for( i = 0; i < 25; i++ )
array[i] = i;
For the condition i < 25, I get a seg fault without fail. When I change it to i < 15, I receive no seg fault.
If I remember correctly, the only difference between an array of pointers and an array is that the memory allocated to an array is located on the stack as opposed to the heap (not sure about this). With that in mind, and considering the fact that i < 15 when array[10] doesn't produce any seg faults, why would i < 25 be an issue? Isn't the array at the top of the stack during that for loop? Why would it care about 100 extra bytes when it didn't care about 60 extra bytes? Why isn't the ceiling for that array buffer all the way to the end of whatever arbitrary chunk of memory is reserved for the whole stack?
Hopefully all of this made sense to whoever decides to read a slightly inebriated man's ramblings.
If I'm understanding this correctly, did my pointer exceed its reserved memory limit and just so happen to be in the clear because nothing adjacent and to the right of it was occupied by other data?
Pretty much. Except that you're not "in the clear" because adjacent things probably were occupied by other data and your code simply stomped on that memory and changed the values. You might never notice a problem, or you might notice a problem much later. Either way, it's undefined behaviour.
Welcome to the glorious world of C!
The memory allocation functions (malloc, calloc, realloc, etc) give you memory that's on the heap. When you call one of them and your program doesn't have enough space, it makes a system call to get more. It doesn't do this in precise increments though (it often will do so in some number of whole page increments). When you're indexing past the end of your array (or even before the beginning of it) you are still within the bounds of your program's legal address space. Only when you leave the segment your program owns will you get a Segmentation Violation.
I highly recommend using Valgrind to inspect your program, especially if you are deliberately trying to learn about memory by breaking things. Among other things, it will store canary values on either side of allocations to help you figure out when you're accessing out of bounds and warn you about double frees and memory leaks.
When you call malloc, you might be given more memory than you need it because memory is allocated in multiples of a common block size. If block size is 64bytes and you ask for only 10 bytes, then the OS will give you 64 bytes, hence you can still access memory beyond your requested range which is the behavior your program is observing.
As others said, undefined behaviour doesn't mean your program will crash under all circumstances.
It completely depends on what is supposed to be there where you overwrite the data.
There may be nothing, as the C lib hasn't allocated the program there,
You may have overwritten important administration information which is used later and only then leads to a crash,
or whatever else.
For helping you to understand what really happens under the hood, printing addresses (such as printf("%p\n", s_pair); or anything like that) may be helpful, as well as compiling the program to readable assembler mnemonics (such as gcc -S filename.c -o-)

Check if 2d pointer array has user defined value in C?

Sample code:
float** a;
a = (float**) malloc(numNodes * sizeof(float*));
for(int i=0; i<`numNodes`; i++)
{
a[i] = (float*)malloc((numNodes-1) * sizeof(float));
}
I am creating a dynamic 2d array above. Before populating, I noticed that each block in the array already holds this value: -431602080.000000 and not NULL. Why is this?
There are situations where not all spaces within the array are used.
So, my query is simple, Is there an elegant way to check if the each block has this default value or a user defined value?
Thanks in advance.
The content of memory allocated with malloc (as well as of variables allocated on the stack) is undefined, so it may very well be anything. Usually you get space filled with zeroes (because the OS blanks memory pages that were used by other processes) or residues of the previous use of those memory pages (this is often the case if the memory page belonged to your process), but this is what happens under the hood, the C standard does not give any guarantees.
So, in general there's no "default value" and no way to check if your memory has been changed; however you can init the memory blocks you use with magic values that you're sure that will not be used as "real data", but it'll be just a convention internal to your application.
Luckily, for floating point variables there are several magic values like quiet NaN you can use for this purpose; in general you can use the macro NAN defined in <math.h> to set a float to NaN.
By the way, you shouldn't read uninitialized floats and doubles, since the usual format they are stored in (IEEE 754) contains some magic values (like the signaling NaN) that can raise arithmetic exceptions when they are read, so if your uninitialized memory happens to contain such bit pattern your application will probably crash.
C runtimes are not required to initialize any memory that you didn't initialize yourself and the values that they hold are essentially random garbage left over from the last time that memory was used. You will have to set them all to NULL explicitly first or use calloc.
Extending the good answer of Matteo Italia:
The code of initialization of a single array would look like:
float* row;
row = malloc( numNodes*sizeof(float) );
for (int i=0; i<numNodes; ++i) {
row[i] = nanf(); // set a Not-a-Number magic value of type float
}
(I'll leave it up to you to change this for your multi-dimensional array)
Then somewhere:
float value = ...; // read the array
if (isnan(value)) {
// not initialized
} else {
// initialized - do something with this
}
One thing is important to remember: NaN == NaN will yield false, so it's best to use isnan(), not == to test for the presence of this value.
In C automatic variables doesn't get automatically initialized. You need to explicitly set your variable to 0, if it's what you want.
The same is true for malloc that does'n initialize the space on the heap it allocates. You can use calloc if you want to initialize it:
a = malloc( numNodes*sizeof(float*) ); // no need to initialize this
for ... {
a[i] = calloc( numNodes-1, sizeof(float) );
}
Before populating, I noticed that each block in the array already holds this value: -431602080.000000 and not NULL. Why is this?
malloc() doesn't initialize the memory which it allocates. You need to use calloc() if you want 0 initialization
void *calloc(size_t nelem, size_t elsize);
The calloc() function allocates unused space for an array of nelem elements each of whose size in bytes is elsize. The space shall be initialized to all bits 0.

Resources