This is a matrix A which I am defining dynamically . Values of a and b is 9 so its a 9x9 matrix.
double **A = (double **) malloc(a * sizeof(double *));
for (int i = 0; i < a; i++) {
A[i] = (double *) malloc(b * sizeof(double ));
}
Now when I am doing the following code , I get segmentation error . z=49 in this case
for(j=0; j<z; j++){
for(i=0; i<z; i++){
A[j][i]=1.0;
}
}
I tried changing the values of z and its working till z=30.
I am loping over the columns and then loop over the rows and change the value for specific elements
You're allocating a data structure representing a 9 x 9 matrix. You're attempting to assign values as if it had dimensions (at least) 49 x 49. That grossly overruns the bounds of your object, producing undefined behavior. A segmentation fault / segmentation error is a common manifestation of undefined behavior arising from such a situation.
That the UB manifests differently for z between 10 and 30 is irrelevant. In particular, if its manifestation happens to be consistent with your conclusion that "it works", that does not in any way mean that the program is correct or safe, nor does it say anything about how the UB should manifest for other values of z, or even that it should reliably manifest the same way for z in this range.
I get segmentation error . z=49 in this case
If you allocate 9x9 array and try to access elements outside the matrix bounds you invoke Undefined Behaviour (UB).
Your z has to be 9 in this case not 49
If either the value of a or the value of b used to allocate arrays is less than the value of z then you indeed can get a segmentation error because actually there will be undefined behavior accessing memory outside the allocated arrays.
So if a and b are equal to 9 then the variable z also shall not be greater than 9.
Also if you want to use a square matrix then there is no great sense to use two different variables a and b to allocate arrays. It is enough and more clear to use only one variable throughout your program.
If your compiler supports variable length arrays then you could allocate a two-dimensional array the following way calling the function malloc only once:
int z = 49;
double ( *A )[z] = malloc( sizeof( double[z][z] ) );
for ( j = 0; j < z; j++ )
{
for ( i = 0; i < z; i++ )
{
A[j][i] = 1.0;
}
}
//...
free( A );
Related
#include <stdio.h>
int main(void) {
int *x, *y;
x = malloc(sizeof(int));
for (int i = 0; i < 4; i++)
x[i] = i + 1;
y = x;
for (int i = 0; i < 4; i++)
printf("%d ", y[i]);
}
This works correct and outputs 1 2 3 4.
But when i < 1000000 it gives segmentation fault.
Can someone explain this?
You need to allocate a large enough buffer. You only allocate sizeof(int) which is 4 bytes typically and large enough to hold only one integer. Can't store 1000000 elements in that. It worked for 4 elements out of pure chance, probably because although you were overwriting memory, you didn't clobber anything important. Something like this is what you should use.
#include <stdio.h>
int main(void)
{
int count = 1000000;
int *x, *y;
x = malloc(sizeof(int) * count);
for (int i=0; i < count; i++)
x[i] = i+1;
y = x;
for (int i=0; i < count; i++)
printf("%d ", y[i]);
}
Undefined behaviour is undefined, you cannot justify any outcome whatsoever.
You have memory allocated for one integer, the moment you try to dereference the memory outside that range (i.e., i == 1), you're invoking UB. The only valid access is x[0] and x[0] only.
You only allocated memory for one int:
x = malloc(sizeof(int)); // malloc allocates a memory chunk to only hold one int object.
Indexing x at x[i] = i+1; or y at printf("%d ", y[i]); in the loops with anything other than a value of 0 for i (like x[0] or y[0]) invokes undefined behavior because you would attempt to write to and read from not allocated memory.
"then this means if I don't have any enough buffer, it also will give a segmentation fault for i < 4?"
Exactly. You know that is the bad thing on undefined behavior. It does not need to provide wrong results or errors. So, the i < 4 code is broken, too.
Since you written to "only" 12 bytes after the allocated memory (since sizeof(int) common is 4), it might have worked because there was no other necessary information in memory thereafter, but your code is absolutely broken nonetheless.
you defined less memory than the memory you used causing your program to write after that memory zone and alterate the stack fo the program, this is also the case of the buffer overflow vulnerability in C and C++, increment the buffer size
I'm trying to allocate memory for a double type array to use it with GNU Scientific Library.
The code in using for this is something like
double *x_i, *y_i, *x_e, *y_e, data[MAX_SIZE][2];
int n_i, n_e, n_data;
...
x_i = (double *)malloc(n_i * sizeof(double));
y_i = (double *)malloc(n_i * sizeof(double));
x_e = (double *)malloc(n_e * sizeof(double));
y_e = (double *)malloc(n_e * sizeof(double));
for (int i = 0; i < n_data; i++){
if (data[i][1] > 0){
x_e[i] = data[i][0];
y_e[i] = data[i][1];
}
else{
x_i[i] = data[i][0];
y_i[i] = data[i][1];
}
}
With n_i + n_e = n_data.
Apparently, sizeof(x/y_e/i) after malloc is 8, but should be arround 50*sizeof(double). The values attributed after the for loop to x_e/i[i] and y_e/i[i] are not consistent, they change as I change the order of attribution, sometimes returning -nan. Values of data[][], n_i, n_e and n_data are consistent with I expect, and if I print x_e/i[i] and y_e/i[i] values inside the for loop they look correct, but outside that loop they change.
Thank you, and sorry if this is a redundant or bad formulated question.
In addition to sizeof(x/y_e/i) actually returning sizeof(double*) (as other users have mentioned), your for-loop is incorrect:
If n_i + n_e == n_data, then you will always hit a case where attempting to access x/y_e/i[i] will take you out of bounds. To avoid this, you could keep track of x/y_e's and x/y_i's indices separately, perhaps like this:
int i_e = 0, i_i = 0;
for (int i = 0; i < n_data; i++){
if (data[i][1] > 0){
x_e[i_e] = data[i][0];
y_e[i_e] = data[i][1];
i_e++;
}
else{
x_i[i_i] = data[i][0];
y_i[i_i] = data[i][1];
i_i++;
}
}
By the end of the loop, you should find that i_e + i_i == n_data and that the values assigned to x_e/i and y_e/i are consistent.
First, sizeof(x_i) with x_i being of type double* is the size of a pointer (probably 8 on your system), and not the size of the memory allocated. There is no way to get the size of the memory block to which a pointer points solely from the pointer.
Second, the "changing values" of the array that are not set in the loop are caused by having not initialized this portion of the array. Actually you yield undefined behaviour, most likely printing "garbage" when accessing these values. To overcome this, use calloc instead of malloc. calloc zero-initializes the memory block allocated, and according to IEEE standards, floating point values with all bits set to 0 represent the floating point value 0.0:
x_i = calloc(n_i, sizeof(double));
I have observed that memory allocated for array seems to be dynamic.
Here is the sample code I found in this tutorial:
#include <stdio.h>
main() {
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
n = n + 1;
while( j >= k){
LA[j+1] = LA[j];
j = j - 1;
}
LA[k] = item;
printf("The array elements after insertion :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}
and sample output:
The original array elements are :
LA[0]=1
LA[1]=3
LA[2]=5
LA[3]=7
LA[4]=8
The array elements after insertion :
LA[0]=1
LA[1]=3
LA[2]=5
LA[3]=10
LA[4]=7
LA[5]=8
How its working I did not get.
First, a general statement, for an array defined without explicit size and initialized using brace-enclosed initializer, the size will depend o the elements in the initializer list. So, for your array
int LA[] = {1,3,5,7,8};
size will be 5, as you have 5 elements.
C uses 0-based array indexing, so the valid access will be 0 to 4.
In your code
LA[j+1] = LA[j];
trying to access index 6, (5+1) which is out of bound access. This invokes undefined behavior.
Output of a code having UB cannot be justified in any way.
That said, main() is technically an invalid signature as per latest C standards. You need to use at least int main(void) to make the code conforming for a hosted environment.
The code has a buffer overflow bug! Arrays in C cannot be extended! You need to allocate enough space when you declare/define it.
You can declare additional space by supplying a size in the declaration:
int LA[10] = {1,3,5,7,8};
LA will now have room for 10 elements with index 0 through 9.
If you want more flexibility you should use a pointer and malloc/calloc/realloc to allocate memory.
Note:
There is a second bug in the copying. The loop starts one step too far out.
With j starting at 5 and assigning index j+1 the code assigns LA[6], which is the 7th element. After the insertion there are only 6 elements.
My conclusion from these 2 bugs is that the tutorial was neither written nor reviewed by an experienced C programmer.
To add on to the other answers, C/C++ do not do any bounds checking for arrays.
In this case you have a stack allocated array, so as long as your index does not leave stack space, there will be no "errors" during runtime. However, since you are leaving the bounds of your array, it is possible that you may end up changing the values of other variables that are also allocated in the stack if it's memory location happens to be immediately after the allocated array. This is one of the dangers of buffer overflows and can cause very bad things to happen in more complex programs.
running int a strange scenario where malloc is allocating more memory than I ask for:
void function (int array [], int numberOfElements) {
int *secondArray = malloc(sizeof(int) * numberOfElements/2);
for (int i = 0; i < numberOfElements / 2; i++) {
secondArray[i] = array[i];
}
}
Let's say array is a some 10 numbers. When I print out secondArray after the above code, I get:
so first of all, the array should be 5 elements. But second, why the 0's in the end? I'm mallocing only space for 10/2 = 5 ints.
EDIT:
printing code:
for (int d = 0; d < numberOfElements; d++) {
printf("%i ", secondArray[d]);
}
hmm I might have just answered my own question here, I'm guessing it's the printing beyond secondArray that shows 0, not the array itself.
-
Actually, the problem is that I was also not doing this:
secondArray[numberOfElements] = '\0';
That is why it was printing beyond.
malloc is actually allocating exactly the right amount.
However, you're accessing memory beyond the allocation.
What exists there is completely undefined and could really be anything.
In your case, it was one "junk" number and four zeroes.
You are just lucky. Malloc can and sometimes does ask from more memory off the OS - Taking into account paging. Sometimes it does not even need to ask the OS for memory as it has asked for extra earlier. Therefore the malloc could ask for a page of memory - more that enough to satisfy your request and the extra memory happens to be filled with zeros.
You are in the land of undefined behaviour. So all bets are off.
/** its print 0 0 0 0 because in C no array bound if you define your array
* size is 4 but
* you want to store data more than array size you can store so you print your
* array.
* for(i = 0; i < numberOfElements; i++) its give data and 0 also because you
* store the data
* only 5 position but you print it max size so it give you 0 0 0
*/
int *secondArray = malloc(sizeof(int) * numberOfElements/2); // no matter either use it or
int *secondArray = malloc(sizeof(int));
// ^^^ this will take same memory
I am working on a simple softmodem program. The modem is designed to implement the Audio FSK of a dial-up modem and should be able to initiate a phone call by emitting DTMF tones. Currently I am having some problems with a function which will generate sine values.
double* generate_sine( int numberOfElements, double amplitude,
double phase_in_degrees, double numberOfCycles)
{
static int i;
double *sine_output;
sine_output = malloc( numberOfElements*sizeof(double) );
for( i=0; i<numberOfElements; i++ )
{
sine_output[i] = (amplitude*sin(( (2.0*M_PI*i*numberOfCycles)/(double)numberOfElements )+
((M_PI*phase_in_degrees)/180 )));
}
return sine_output;
}
There is a segmentation error in the function. the variable "i" appears to become a pointer after the first iteration of the loop, its value is 4206692. sine_ptr also has a valid address until the second iteration of the loop at which point it become 0 (NULL).
Here is where the function is called. DEFAULT_PHASE = 0.0
int main()
{
int i;
int numElements = 10;
double* sine_ptr = generate_sine( numElements, 0.5, DEFAULT_PHASE, 440 );
for( i=0; i<numElements; i++)
{
printf( "%e \n", *(sine_ptr + i ) );
}
free(sine_ptr);
return 0;
}
After taking all of the edit suggested into consideration I was able to solve the problem in my code, thank you very much for any help that you gave me.
EDIT Added another point.
Issue Number 1
You are allocating enough memory for 5 elements (numberOfElements is 5). You are then trying to print 10 elements from the initial point. The last 5 elements will be accessing unallocated space and can result in undefined behavior. Including segmentation faults.
Issue Number 2
You are not freeing the pointer to the allocated space but a location 10 places later. This will also cause other problems if you solve the segmentation fault.
Issue Number 3
This is one of the minor ones. But sine_ptr is double, and trying to show it as int is undefined. will cause compiler warnings. Even with warnings, the numbers are downcasted. In your case the output will be all zeros. To see correct results, use %lf.
Use the following code.
int main()
{
int i;
int numElements = 5;
double* sine_ptr = generate_sine( numElements, 0.5, DEFAULT_PHASE, 440 );
for( i=0; i<numElements; i++)
{
printf( "%lf \n", *(sine_ptr + i) );
}
free(sine_ptr);
return 0;
}