I'm writing a program that converts an array of integer vectors to an adjacency matrix , an (n+1)x(n+1) array. When in the function i have written to do this the dynamic memory allocation from setting up the int** seems to overwrite the n+1 and n+n elements of the integer vector.
int** makeAdjMatrix(IntVec* Vec, int length) { //allocates a new nxn array
printf(" madm test %d \n" , Vec[1]->data[6]);
//confirming that the intvec entered okay
int** new;
new = (int**)malloc(length+1*length+1*sizeof(int*))
printf(" madm test %d \n" , Vec[1]->data[6]);
// confirming that something happenend to the intvec
for (int i = 0; i <= length + 1; i++) {
new[i] = (int*)malloc(length + 1*sizeof(int));
}
for (int i = 1; i <= length+1; i++) {
for (int j = 1; j <= length+1; j++) {
new[i][j] = 0;
}
}
outputs normally for all elements in the vector data structure except those n+1 and above. n in this case being 5.
the above code prints
test 1
test 33
segfault
(because there is no 33rd indices in the array which the code referrences later)
is this memory exhaustion? how am I overwriting a previously allocated array on the heap? this might be a bit vague, this is my first question go easy on me. by the way this only happens when the vector array has repeated identical input.
how bad did I mess up?
Related
I tried a lot of things to do but it still show me the same, that there is unhandled exception: access violation writing location in VS. But it doesn't happen when i sorting 1d array. What can I try next?
int main(void) {
static int a[3][4]{}, ab[3][4]{};
int i, j, k, N, M;
int* a1=nullptr;
printf("Matrica mora da ima velicinu 3 sa 4\n");
printf("Enter the order \n\n\t");
scanf_s("%d%d",&N ,&M);
for (i = 0;i < M;++i)
{
for (j = 0;j < N;++j)
{
scanf_s(" %d", &a[i][j]);
ab[i][j] = a[i][j];
}
printf("\n");
}
for (i = 0;i < M;++i) {
for (j = 0;j < N;++j) {
printf(" %d", a[i][j]);
}
printf("\n ");
}
//classic sorting
for (i=0; i < M; ++i)
{
for (j = 0;j < N;++j)
{
for (k = j + 1;j < N;++k)
if (a[i][j] > a[i][k])
{
*a1 = a[i][j]; // there is exception thrown
a[i][j] = a[i][k];
a[i][k] = *a1;
}
}
}
First off, there is a problem with static allocation of arrays, but there is no sanitization of N and M after the user inputs them. That means that you allocate only a matrix of 3x4, but the user can input and write to a matrix of any dimensions (e.g. 10x10), which could lead to access violation.
I'd recommend either having sanitation of the input values, e.g.
// It's always better to have limits as constant.
const int MAX_N = 3;
const int MAX_M = 4;
static int a[MAX_N][MAX_M];
...
scanf_s("%d%d",&N ,&M);
// Check if the dimensions can be fitted into the statically allocated array.
if(N > MAX_N || N <= 0 || M > MAX_M || M < 0)
{
// indicate invalid dimensions, either by returning from main with -1
// or calling exit(-1), or throwing an exception.
return -1;
}
In case the input didn't exceed 3x4, another thing that could be problematic - i goes from 0 to M, not N (what I would expect), which could also be problematic. The way matrix addressing works in C/Cpp is that the matrix is linearized into an array, and accessing it with a[i][j] leads to accessing the array with a[i*MAX_J + j]. In your case, the array has 12 elements (3x4), and MAX_J=4, so accessing it with a reverse set of indexes a[4][3] will access a[4*4+3]=a[19], which will access memory from outside of the array.
On the access violation writing problem, a1 isn't allocated, so when you try do execute *a1= ... you are writing to nullptr, which is a protected address, hence the access violation when writing. The way to solve this is either to:
have a1 be a int variable (not a pointer)
first allocate memory for a1 by executing a1 = malloc(sizeof(int)); and then freeing it after use with free(a1) (but since it's only a single element, I'd recommend converting a1 to int instead)
assign the address of the matrix element like a1=&a[i][j], but that would not be valid logically in your case (after that, you write into the location the pointer is pointing to, so the original value will be lost).
The reason why it's not happening for the 1d array is probably because of the inverted dimensions - the matrix would probably be 1x4, but you will be accessing it as 4x1, and you are sorting all the values with j index from 0 to 1, and since there is only one value you would not enter the k loop.
I'm trying to write a basic fixed size array of dynamically allocated array(for when we only know one dimension of a 2D array) and getting the user input for the matrix.
I've learnt that after you declared the dynamically allocated 2D matrix, you can accessed it like a fixed length 2D array.
So I tried to use scanf to get user input for the dynamically allocated 2D array just like how I did for the fixed length 2D array.
For fixed length 2D array, I did this and it works:
long bar[3][3];
printf("input 9 elements: ");
for (r = 0; r < 3; r += 1) {
for (c = 0; c < 3; c += 1) {
scanf("%ld", &bar[r][c]);
}
}
But when I did this for fixed size array of dynamically allocated array:
long *buckets[3], no_of_cols, no_of_rows, c;
printf("number of elements in each cols: ");
scanf("%ld", &no_of_cols);
for (no_of_rows = 0; no_of_rows < 3; no_of_rows += 1) {
buckets[no_of_rows] = calloc( no_of_cols, sizeof(long));
}
long m = no_of_cols * 3;
printf("input %ld elements: ", m);
for (no_of_rows = 0; no_of_rows < 3; no_of_rows += 1) {
for(c = 0; c < no_of_cols; c += 1) {
scanf("%ld" &buckets[no_of_rows][c]);
}
}
I expect the program to write the user input into the array buckets. But when I run the program, it came out this error:
error: invalid operands to binary expression
('char *' and 'long')
scanf("%ld" &buckets[no_of_rows][c]);
I don't understand what I'm doing wrong for the dynamically allocated 2D array causing this error. Please help me.
So basically according to definition of array we cannot change array size. But if I am adding element to a same array by shifting other elements to the right of array, so the array size is going to increase.
How this is possible?
#include<stdio.h>
int main() {
int n, j, k, item;
printf("Enter size of array:\n");
scanf("%d", &n);
printf("Enter element to insert and position of element:\n");
scanf("%d,%d", &item, &k);
int a[n];
for (j = 0; j < n; j++) {
printf("Enter a[%d] element:\n", j);
scanf("%d", &a[j]);
}
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j];
j = j - 1;
}
a[k - 1] = item;
for (j = 0; j <= n; j++) {
printf("%d\n", a[j]);
}
}
Shifting the contents of the array to the right will not resize the array. If the array was not already large enough to hold the result of the shift, then you have overrun the array object, and have induced undefined behavior.
There is no way to dynamically increase the size of a variable with static or auto duration (e.g., global or local variables), and this includes arrays. If your compiler supports variable length arrays (VLAs), changing the value of the expression controlling the dimension of the array does not affect the array's size.
int main (void) {
int n = 3;
int v[n];
printf("%zu\n", sizeof(v));
++n;
printf("%zu\n", sizeof(v));
}
The program above will print the same value twice.
I am not entirely sure what you're asking, but for any readers interested in knowing how to dynamically change the size of an array in C: if an array is declared in stack memory, its size cannot change. However, a block of memory intended to be used as an array is declared on the heap (i.e. with malloc or calloc), can be reallocated with a different size if necessary:
int *data = malloc(10 * sizeof(int)), *data2 = NULL;
int i;
if(data == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++)
{
data[i] = i;
}
data2 = realloc(data, 11 * sizeof(int));
if(data2 == NULL)
{
free(data);
perror("realloc");
exit(EXIT_FAILURE);
}
else
{
data = data2;
}
data[10] = 10;
for (i = 0; i < 11; i++)
printf("%d ", data[i]);
free(data);
data = NULL;
Shifting elements in an array down one element will not change its size.
If you declare an array as
T a[N]; // assume N is a constant expression
then a can only ever hold N elements of type T - no more, no less. You cannot add extra elements to the array, nor can you remove elements from the array.
However...
C does not force any bounds checking on array subscripting, so it's possible that you can read or write past the end of the array such as
a[N + 2] = x;
The behavior on doing so is undefined - your program may work as expected, or it may crash immediately, or you may corrupt other objects in the program. The runtime environment will (most likely) not throw an IndexOutOfBounds-type exception.
There is a thing called a variable-length array that was added in C99, where the array size is not a constant expression:
size_t size = some_value();
T a[size];
Variable length arrays are only variable length in the sense that their size isn't determined until runtime - however, once defined, their size is fixed throughout their lifetime, and like regular arrays, they cannot grow as new items are added.
If you dynamically allocate a chunk of memory using
T *a = malloc( sizeof *a * some_size );
then you can grow or shrink that chunk of memory using realloc:
T *tmp = realloc( a, sizeof *a * (some_size * 2) );
if ( tmp )
{
a = tmp;
some_size *= 2;
}
.... array we cannot change .. But if I (do something special) ... the array size is going to increase.
How this is possible?
Undefined behavior
Arrays cannot change size once defined.
Code attempts to assign a[j + 1] with j = n-1 and that is a[n]. This is outside array a[] and so undefined behavior. Rest of code is irrelevant for at that point anything is possible, code crash, error report, even apparent successful array expansion, etc.
int a[n];
...
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j]; // To attempt access to `a[n]` is UB
I am able to declare in a good way two matrices A and B.
But, when using the memcpy (to copy B from A), B gives me arrays of 0s.
How can I do? Is my code correct for using memcpy?
int r = 10, c = 10, i, j;
int (*MatrixA)[r];
MatrixA=malloc(c * sizeof(*MatrixA));
int (*MatrixB)[r];
MatrixB=malloc(c * sizeof(*MatrixB));
memcpy(MatrixB,MatrixA,c * sizeof(MatrixA));
for(i=1;i<r+1;i++)
{
for (j = 1; j < c+1; j++)
{
MatrixA[i][j]=j;
printf("A[%d][%d]= %d\t",i,j,MatrixA[i][j]);
}
printf("\n");
}
printf("\n");printf("\n");printf("\n");printf("\n");printf("\n");
for(i=1;i<r+1;i++)
{
for (j = 1; j < c+1; j++)
{
printf("B[%d][%d]= %d\t",i,j,MatrixB[i][j]);
}
printf("\n");
}
You copied contents before initializing MatrixA .And also you access index out of bound (r+1 evaluates 11 which is out of bound) causing UB. Do this instead -
for(i=0;i<r;i++) // i starts from 0
{
for (j =0; j < c; j++) // j from 0
{
MatrixA[i][j]=j;
printf("A[%d][%d]= %d\t",i,j,MatrixA[i][j]);
}
printf("\n");
}
memcpy(MatrixB,MatrixA,c * sizeof(*MatrixA)); // copy after setting MatrixA
for(i=0;i<r;i++) // similarly indexing starts with 0
{
for (j =0; j < c; j++)
{
printf("B[%d][%d]= %d\t",i,j,MatrixB[i][j]);
}
printf("\n");
}
Is my code correct for using memcpy?
No, your code is wrong, but that's less of a memcpy problem. You're simply doing C arrays wrong.
int r = 10, c = 10, i, j;
int (*MatrixA)[r];
MatrixA=malloc(c * sizeof(*MatrixA));
Ok, MatrixA is now a pointer to a 10-element array of integers right? So the compiler reserves memory for ten ints; however, in the malloc line, you overwrite that with a pointer to a memory region of ten times the size of a single integer. A code analysis tool will tell you that you've built a memory leak.
These mistakes continue throughout your code; you will have to understand the difference between statically allocated C arrays and dynamic allocation using malloc.
I tried the following to reallocate a 2D float array whose size chages from 2X2 to 3X3. The code throws a segfault while trying to realloc memory for weights[2].
num_vertices = 2;
float **weights = malloc(num_vertices*sizeof(float *)); // weight array matrix
for(i = 0; i < num_vertices; i++){
weights[i] = malloc(num_vertices*sizeof(float));
}
num_vertices = 3;
weights = realloc(weights, num_vertices*sizeof(float *)); // weight array matrix
for(i = 0; i < num_vertices; i++){
weights[i] = realloc(weights[i], num_vertices*sizeof(float));
}
Of course, I can free the 2D array and malloc again, but I was looking for a more elegant solution. Any ideas?
The problem is that weights[2] contains garbage after you realloc weights.
You probably want to do something like this:
new_vertices = 3;
weights = realloc(weights, new_vertices*sizeof(float *));
for(i = 0; i < new_vertices; i++)
{
if (i >= num_vertices)
weights[i] = NULL;
weights[i] = realloc(weights[i], new_vertices*sizeof(float));
}
num_vertices = new_vertices;
Note that you have a potential memory leak if realloc ever fails. Since you have no error checking yet though this probably doesn't matter for now.
The realloc of weights[2] is trying to realloc unallocated memory, since weights[2] was never assigned any pointer.
Usually, if you want a 2D array, just use wegihts[width*y + x] to index into the array, instead of making an array of pointers.
You can't loop to the new vertice count, as that part of the outer array is not allocated yet and contain uninitialized data. Instead loop to the new num_vertices - 1 and reallocate, then create a brand new weights[num_verticees - 1].