struct inner element's value assignment failed in c - c

context: https://stackoverflow.com/a/72238514/15603477
#include<stdio.h>
#include<stdlib.h>
#define MAT_SIZE 2
#define MAT_COUNT 3
typedef double mat[MAT_SIZE][MAT_SIZE];
typedef struct matList{
const char *name;
mat matrix;
}matList;
void init_mat(mat m)
{
for(int i = 0; i < MAT_SIZE; i++){
for(int j = 0; j < MAT_SIZE; j++){
m[i][j] = i * 2.1 + (double) j + 1.1;
printf("(i,j)=%f\n",m[i][j]);
}
}
}
//allocate matList.
matList *create_mat(const char *name)
{
matList *tempMat = malloc(sizeof *tempMat);
if(tempMat != NULL)
{
tempMat->name = name;
init_mat(tempMat->matrix);
}
return tempMat;
}
// freematList
void free_matList(matList **mats)
{
if(mats){
for(int i = 0; i < MAT_COUNT; i++){
free(mats[i]);
}
}
}
// return non zero if successful
int allocate_matList(matList **mats)
{
if(mats){
mats[0] = create_mat("MAT_A");
mats[1] = create_mat("MAT_B");
mats[2] = create_mat("MAT_C");
if(mats[0] && mats[1] && mats[2])
return 1;
}
}
int main(void)
{
matList *mats[MAT_COUNT];
if(allocate_matList(mats)){
printf("mat[2] name: %s\n",mats[2]->name);
size_t row = sizeof(mats[2]->matrix) / sizeof (mats[2]->matrix[0]);
size_t col = sizeof(mats[2]->matrix[0]) / sizeof(mats[2]->matrix[0][0]);
printf("row: %ld col: %ld\n",row,col);
for(size_t i = 0; i < row; i++){
for(size_t j = 0; j < col; j++){
printf("%f\t",mats[2]->matrix[row][col]);
}
printf("\n");
}
}
free_matList(mats);
exit(EXIT_SUCCESS);
}
There would be MAT_COUNT of struct matList. each matList's matrix is identical.
expected last print result would be:
1.100000 2.100000
3.200000 4.200000
now the last printf return
0.000000 0.000000
0.000000 0.000000
which means that the values assignment of matrix failed?
(gdb) break 23
Breakpoint 1 at 0x11d9: file array_struct170.c, line 23.
(gdb) s
The program is not being run.
(gdb) run
Starting program: /home/jian/helloc/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, init_mat (m=0x5555555592a8) at array_struct170.c:23
23 for(int i = 0; i < MAT_SIZE; i++){
(gdb) s
24 for(int j = 0; j < MAT_SIZE; j++){
(gdb) s
25 m[i][j] = i * 2.1 + (double) j + 1.1;
(gdb) print m[i][j]
$1 = 0
now I guess the line have problem is
m[i][j] = i * 2.1 + (double) j + 1.1;

for(size_t i = 0; i < row; i++){
for(size_t j = 0; j < col; j++){
printf("%f\t",mats[2]->matrix[row][col]); // <- look closely!
}
printf("\n");
Since row is 2 and col is 2, you are trying to print out matrix[2][2], which is out of bounds. You probably wanted matrix[i][j] instead of matrix[row][col].
By the way, valgrind caught this immediately.

Related

Interleaving array in C

I posted earlier, but I did not properly format or add my code. Say I have an int array x = [1,2,3]. Given a value i, I want to create an array x^i, such that, if i = 3, array x^i = [1,1,1,2,2,2,3,3,3]. If i = 5, array x^i = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5]. I am dynamically allocating memory for this.
However, my code for i = 3 is creating an array = [1,2,3,1,2,3,1,2,3]. I've tried many different things, and I got something like [1,1,1,1,1,1,1,1,1] or [3,3,3,3,3,3,3,3,3] but never the correct answer.
Here is my code:
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i){
int i, j, k, count = 0, max_repeat = 0;
while(min_i <= max_i){
int repeats = (max_i + min_i)/2;
int * temp = realloc(X, size_x * sizeof(int) * repeats);
X = temp;
for(k = 0; k < size_x; ++k){
int idx = size_x - k -1;
temp = &X[idx];
for(j = 0; j < repeats; ++j){
X[idx * repeats + j] = *temp;
}
}
printf("New X: ");
for(i = 0; i < size_x * repeats; i++){
printf("%d ", X[i]);
}
int count = 0;
for(i = 0; i < size_x * repeats; i++){
for(j = 0; j < size_a; j++){
if(A[j] == X[i]){
count++;
i++;
}
}
}
if (count == size_x * repeats){
printf("Low: %d Mid %d High % d Passes\n", min_i, repeats, max_i);
min_i = repeats + 1;
}
else
printf("Low: %d Mid %d High % d Fails\n", min_i, repeats, max_i);
max_i = repeats - 1;
}
}
the variable repeats represents the value i in x^i.
The output is this:
Old X: 1 2 3
New X: 1 1 1 2 2 2 3 3 3 Low: 0 Mid 3 High 6 Fails
New X: 1 1 1 Low: 0 Mid 1 High 2 Fails
New X: Low: 0 Mid 0 High 0 Fails
The first iteration is correct, however, the second iteration should not be [1,1,1], it should be [1,2,3].
Where am I going wrong?
Here you go:
int misleading_function_names_is_bad_practice(size_t xsize, int x[xsize], size_t i)
{
void * const tmp = realloc(x, xsize * sizeof(*x) * i);
if (tmp == NULL) {
return -__LINE__;
}
x = tmp;
for (size_t k = 0; k < xsize; ++k) {
// index of the last original digit counting down
const size_t idx = xsize - k - 1;
const int tmp = x[idx];
for (size_t l = 0; l < i; ++l) {
// fill from the back
x[idx * i + l] = tmp;
}
}
return 0;
}
Live example available at onlinegdb.

Array values changing without reason

This is my code for Project Euler: Problem 11
int main(int argc, char** argv) {
char stevila [1600] = "08022297381500400075040507785212507791084949994017811857608717409843694804566200814931735579142993714067538830034913366552709523046011426924685601325671370236912231167151676389419236542240402866331380244732609903450244753353783684203517125032988128642367102638406759547066183864706726206802621220956394396308409166499421245558056673992697177878968314883489637221362309750076442045351400613397343133957817532822753167159403800462161409535692163905429635314755588824001754243629855786560048357189070544443744602158515417581980816805944769287392138652177704895540045208839735991607975732162626793327986688366887576220720346336746551232639353690442167338253911249472180846293240627636206936417230238834629969826759857404361620733529783190017431497148868116235705540170547183515469169233486143520189196748";
int stevilaGrid [20][20];
int stevilaRacunanje[4][4];
int stevecPoStevilih = 0;
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 20; j++) {
stevilaGrid[i][j] = (stevila[stevecPoStevilih] - 48)*10 + stevila[stevecPoStevilih + 1] - 48;
stevecPoStevilih += 2;
}
}
int rezultat [10];
int najvecji = 0;
int trenutni;
int temp = 0;
for (int i = 0; i < 17; i++) {
for (int j = 0; j < 17; j++) {
//problems start here
for (int k = 0; k < 5; k++) {
for (int l = 0; l < 5; l++) {
temp = stevilaGrid[i + k][j + l];
stevilaRacunanje[k][l] = temp;
}
}
for (int k = 0; k < 5; k++) {
rezultat[k] = stevilaRacunanje[k][0] * stevilaRacunanje[k][1] * stevilaRacunanje[k][2] * stevilaRacunanje[k][3];
rezultat[k+4] = stevilaRacunanje[0][k] * stevilaRacunanje[1][k] * stevilaRacunanje[2][k] * stevilaRacunanje[3][k];
}
rezultat[8] = stevilaRacunanje[0][0] * stevilaRacunanje[1][1] * stevilaRacunanje[2][2] * stevilaRacunanje[3][3];
rezultat[9] = stevilaRacunanje[0][3] * stevilaRacunanje[1][2] * stevilaRacunanje[2][1] * stevilaRacunanje[3][0];
for (int k = 0; k < 10; k++) {
trenutni = rezultat[k];
if(trenutni > najvecji){
najvecji = trenutni;
}
}
}
}
printf("Najvecji zmnozek: %d", najvecji);
return (EXIT_SUCCESS);
}
First I convert the string of numbers into a 2D int array.
Then I try to divide the grid into smaller 4x4 squares with which I can work more easily. That is where the problems start (as marked in the code).
At the very beginning (*i=0,j=0;k=4,j=0*) something strange starts to happen. The values in *stevilaGrid[][]* start to change randomly and seemingly without a reason.
Can somebody please explain this to me. I have tested this behavior on Windows with Cygwin 64bit and Ubuntu with GCC 64bit.
[i + k][j + l];
When i==16 and k==4 or j==16 and j==4 you'll be hitting element [20]
Your array only goes 0...19

Segmentation fault in function implementing Ford-Fulkerson

I'm working on a class assignment and I've run into an issue I haven't been able to figure out. I'm implementing the Ford-Fulkerson algorithm using BFS to find max flow. But while trying to set my Residual Capacity matrix to the given capacity, I hit a segmentation fault. In the test code we received, I can see that the original capacity matrix was passed by value by its address, but I have a feeling that in my code I'm not interacting with it the way I think I am? Which leads me to believe that I may have the same issue recurring elsewhere. I worked with gdb and saw that I hit a segmentation fault on this line here in my nested for loop :
resCap[i][j] = *(capacity + i*n + j);
However, nothing I have tried has worked for me though so I am pretty stumped.
void maximum_flow(int n, int s, int t, int *capacity, int *flow)
{
int i, j, resCap[n][n], path[n]; // residual capacity and BFS augmenting path
int min_path = INT_MAX; // min of the augmenting path
// Assign residual capacity equal to the given capacity
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
resCap[i][j] = *(capacity + i*n + j);
*(flow + i*n + j) = 0; // no initial flow
}
// Augment path with BFS from source to sink
while (bfs(n, s, t, &(resCap[0][0]), path))
{
// find min of the augmenting path
for (j = t; j != s; j = path[j])
{
i = path[j];
min_path = min(min_path, resCap[i][j]);
}
// update residual capacities and flows on both directions
for (j = t; j != s; j = path[j])
{
i = path[j];
if(*(capacity + i*n + j) > 0)
*(flow + i*n + j) += min_flow_path;
else
*(flow + j*n + i) -= min_flow_path;
resCap[i][j] -= min_flow_path;
resCap[j][i] += min_flow_path;
}
}
}
And here is the test code provided to us in case it is needed:
int main(void)
{ int cap[1000][1000], flow[1000][1000];
int i,j, flowsum;
for(i=0; i< 1000; i++)
for( j =0; j< 1000; j++ )
cap[i][j] = 0;
for(i=0; i<499; i++)
for( j=i+1; j<500; j++)
cap[i][j] = 2;
for(i=1; i<500; i++)
cap[i][500 + (i/2)] =4;
for(i=500; i < 750; i++ )
{ cap[i][i-250]=3;
cap[i][750] = 1;
cap[i][751] = 1;
cap[i][752] = 5;
}
cap[751][753] = 5;
cap[752][753] = 5;
cap[753][750] = 20;
for( i=754; i< 999; i++)
{ cap[753][i]=1;
cap[i][500]=3;
cap[i][498]=5;
cap[i][1] = 100;
}
cap[900][999] = 1;
cap[910][999] = 1;
cap[920][999] = 1;
cap[930][999] = 1;
cap[940][999] = 1;
cap[950][999] = 1;
cap[960][999] = 1;
cap[970][999] = 1;
cap[980][999] = 1;
cap[990][999] = 1;
printf("prepared capacity matrix, now executing maxflow code\n");
maximum_flow(1000,0,999,&(cap[0][0]),&(flow[0][0]));
for(i=0; i<=999; i++)
for(j=0; j<=999; j++)
{ if( flow[i][j] > cap[i][j] )
{ printf("Capacity violated\n"); exit(0);}
}
flowsum = 0;
for(i=0; i<=999; i++)
flowsum += flow[0][i];
printf("Outflow of 0 is %d, should be 10\n", flowsum);
flowsum = 0;
for(i=0; i<=999; i++)
flowsum += flow[i][999];
printf("Inflow of 999 is %d, should be 10\n", flowsum);
printf("End Test\n");
}
This line is likely going to segfault, it does using Clang.
int i, j, resCap[n][n], path[n];
You're declaring a very large array on the stack. Just how big can be seen when you try and allocated it using calloc. Try this instead and don't forget to free it using the same sort of loop.
int **resCap2 = calloc(1, n * sizeof(int *));
assert(resCap2);
for (i = 0; i < n; i++) {
resCap2[i] = calloc(1, n * sizeof(int));
assert(resCap2[i]);
}
This is a lot of space ie
(1000 * sizeof(int*) * (1000 * n * sizeof(int)))

malloc 3d memory allocation size [duplicate]

I have a pointer variable int ***a in C. I'm passing it to a function as &a i.e reference. In the function I'm getting a pointer variable of type int ****a.
I'm allocating memory like this.
*a=(int***)malloc(no1*sizeof(int**));
some loop from 0 to no1
(*a)[++l]=(int**)malloc((no1+1)*sizeof(int*));
some loop from 0 to no1
(*a)[l][h]=(int*)malloc(2*sizeof(int));
This is only the time I allocated memory. The actual program is not given; no error here.
But when I'm going to do this:
(*a)[l][h][0]=no1;
It's giving me a "Segmentation Fault" error and I can't understand why.
UPDATE:
I have wrote a sample program which is to allocate the memory only. This is also giving "segmentation fault" error.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
void allocate(int ****a)
{
int i,j,k;
if(((*a)=(int***)malloc(5*sizeof(int**)))==NULL)
{
printf("\nError in allocation of double pointer array\n");
exit(0);
}
for(i=0;i<5;i++)if(((*a)[i]=(int**)malloc(4*sizeof(int*)))==NULL)
{
printf("\nError in allocation of single pointer array on index [%d]\n",i);
exit(0);
}
for(i=0;i<5;i++)
for(j=0;j<4;i++)
if(((*a)[i][j]=(int*)malloc(3*sizeof(int)))==NULL)
{
printf("\nError in allocation of array on index [%d][%d]\n",i,j);
exit(0);
}
for(i=0;i<5;i++)
for(j=0;j<4;i++)
for(k=0;k<3;k++)
(*a)[i][j][k]=k;
}
main()
{
int ***a;
int i,j,k;
allocate(&a);
for(i=0;i<5;i++)
for(j=0;j<4;i++)
for(k=0;k<3;k++)
printf("\na[%d][%d][%d] = %d ",i,j,k,a[i][j][k]);
}
Revised code from question
Your code has:
for(i=0;i<5;i++)
for(j=0;j<4;i++)
several times. The second loop should be incrementing j, not i. Be very careful with copy'n'paste.
This code does not crash (but does leak).
#include <stdio.h>
#include <stdlib.h>
void allocate(int ****a);
void allocate(int ****a)
{
int i,j,k;
printf("allocate: 1B\n");
if(((*a)=(int***)malloc(5*sizeof(int**)))==NULL)
{
printf("\nError in allocation of double pointer array\n");
exit(0);
}
printf("allocate: 1A\n");
printf("allocate: 2B\n");
for(i=0;i<5;i++)
if(((*a)[i]=(int**)malloc(4*sizeof(int*)))==NULL)
{
printf("\nError in allocation of single pointer array on index [%d]\n",i);
exit(0);
}
printf("allocate: 2A\n");
printf("allocate: 3B\n");
for(i=0;i<5;i++)
for(j=0;j<4;j++)
if(((*a)[i][j]=(int*)malloc(3*sizeof(int)))==NULL)
{
printf("\nError in allocation of array on index [%d][%d]\n",i,j);
exit(0);
}
printf("allocate: 3A\n");
printf("allocate: 4B\n");
for(i=0;i<5;i++)
for(j=0;j<4;j++)
for(k=0;k<3;k++)
(*a)[i][j][k]=k;
printf("allocate: 4A\n");
}
int main(void)
{
int ***a;
int i,j,k;
allocate(&a);
for(i=0;i<5;i++)
for(j=0;j<4;j++)
for(k=0;k<3;k++)
printf("a[%d][%d][%d] = %d\n",i,j,k,a[i][j][k]);
}
Previous answers
Since you've not shown us most of the code, it is hard to predict how you're mishandling it, but equally, since you are getting a core dump, you must be mishandling something.
Here is some working code — not checked with valgrind since that is not available for Mac OS X 10.8 — that seems to work. The error recovery for allocation failure is not complete, and the function to destroy the fully allocated array is also missing.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int ***allocate_3d_array(int no1, int ****a)
{
*a = (int***)malloc(no1 * sizeof(int**));
if (*a == 0)
return 0;
for (int l = 0; l < no1; l++)
{
if (((*a)[l]=(int**)malloc((no1+1)*sizeof(int*))) == 0)
{
while (l > 0)
free((*a)[--l]);
return 0;
}
}
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
if (((*a)[l][h]=(int*)malloc(2*sizeof(int))) == 0)
{
/* Leak! */
return 0;
}
}
}
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
(*a)[l][h][k] = 10000 * l + 100 * h + k;
return *a;
}
int main(void)
{
int no1 = 5;
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
printf("a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
// free memory - added by harpun; reformatted by Jonathan Leffler
// Would be a function normally — see version 2 code.
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
free(a[l][h]);
free(a[l]);
}
free(a);
}
return 0;
}
Sample output:
a[0][0][0] = 000000 a[0][0][1] = 000001
a[0][1][0] = 000100 a[0][1][1] = 000101
a[0][2][0] = 000200 a[0][2][1] = 000201
a[0][3][0] = 000300 a[0][3][1] = 000301
a[0][4][0] = 000400 a[0][4][1] = 000401
a[1][0][0] = 010000 a[1][0][1] = 010001
a[1][1][0] = 010100 a[1][1][1] = 010101
a[1][2][0] = 010200 a[1][2][1] = 010201
a[1][3][0] = 010300 a[1][3][1] = 010301
a[1][4][0] = 010400 a[1][4][1] = 010401
a[2][0][0] = 020000 a[2][0][1] = 020001
a[2][1][0] = 020100 a[2][1][1] = 020101
a[2][2][0] = 020200 a[2][2][1] = 020201
a[2][3][0] = 020300 a[2][3][1] = 020301
a[2][4][0] = 020400 a[2][4][1] = 020401
a[3][0][0] = 030000 a[3][0][1] = 030001
a[3][1][0] = 030100 a[3][1][1] = 030101
a[3][2][0] = 030200 a[3][2][1] = 030201
a[3][3][0] = 030300 a[3][3][1] = 030301
a[3][4][0] = 030400 a[3][4][1] = 030401
a[4][0][0] = 040000 a[4][0][1] = 040001
a[4][1][0] = 040100 a[4][1][1] = 040101
a[4][2][0] = 040200 a[4][2][1] = 040201
a[4][3][0] = 040300 a[4][3][1] = 040301
a[4][4][0] = 040400 a[4][4][1] = 040401
Compare this with what you've got. You could add many more diagnostic print messages. If this doesn't help sufficiently, create an SSCCE (Short, Self-Contained, Correct Example) analogous to this that demonstrates the problem in your code without any extraneous material.
Version 2 of the code
This is a somewhat more complex version of the code that simulates memory allocation failures after N allocations (and a test harness that runs it with every value of N from 0 up to 35, where there are actually only 30 allocations for the array. It also includes code to release the array (similar to, but different from, the code that was edited into my answer by harpun. The interaction at the end with the line containing the PID means that I can check memory usage with ps in another terminal window. (Otherwise, I don't like programs that do that sort of thing — I suppose I should run the ps from my program via system(), but I'm feeling lazy.)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int fail_after = 0;
static int num_allocs = 0;
static void *xmalloc(size_t size)
{
if (fail_after > 0 && num_allocs++ >= fail_after)
{
fputs("Out of memory\n", stdout);
return 0;
}
return malloc(size);
}
static int ***allocate_3d_array(int no1, int ****a)
{
*a = (int***)xmalloc(no1 * sizeof(int**));
if (*a == 0)
return 0;
for (int l = 0; l < no1; l++)
{
if (((*a)[l]=(int**)xmalloc((no1+1)*sizeof(int*))) == 0)
{
for (int l1 = 0; l1 < l; l1++)
free((*a)[l1]);
free(*a);
*a = 0;
return 0;
}
}
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
if (((*a)[l][h]=(int*)xmalloc(2*sizeof(int))) == 0)
{
/* Release prior items in current row */
for (int h1 = 0; h1 < h; h1++)
free((*a)[l][h1]);
free((*a)[l]);
/* Release items in prior rows */
for (int l1 = 0; l1 < l; l1++)
{
for (int h1 = 0; h1 < no1; h1++)
free((*a)[l1][h1]);
free((*a)[l1]);
}
free(*a);
*a = 0;
return 0;
}
}
}
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
(*a)[l][h][k] = 10000 * l + 100 * h + k;
return *a;
}
static void destroy_3d_array(int no1, int ***a)
{
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
free(a[l][h]);
free(a[l]);
}
free(a);
}
}
static void test_allocation(int no1)
{
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
for (int k = 0; k < 2; k++)
{
if (a[l][h][k] != l * 10000 + h * 100 + k)
printf("a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
}
}
}
}
destroy_3d_array(no1, a);
}
int main(void)
{
int no1 = 5;
for (fail_after = 0; fail_after < 33; fail_after++)
{
printf("Fail after: %d\n", fail_after);
num_allocs = 0;
test_allocation(no1);
}
printf("PID %d - waiting for some data to exit:", (int)getpid());
fflush(0);
getchar();
return 0;
}
Note how painful the memory recovery is. As before, not tested with valgrind, but I take reassurance from harpun's test on the previous version.
Version 3 — Clean bill of health from valgrind
This code is very similar to the test in version 2. It fixes a memory leak in the clean-up when a memory allocation fails in the leaf level allocations. The program no longer prompts for inputs (much preferable); it takes an optional single argument that is the number of allocations to fail after. Testing with valgrind showed that with an argument 0-6, there were no leaks, but with argument 7 there was a leak. It didn't take long to spot the problem and fix it. (It's easier when the machine running valgrind is available — it was powered down over the long weekend for general site electrical supply upgrade.)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int fail_after = 0;
static int num_allocs = 0;
static void *xmalloc(size_t size)
{
if (fail_after > 0 && num_allocs++ >= fail_after)
{
fputs("Out of memory\n", stdout);
return 0;
}
return malloc(size);
}
static int ***allocate_3d_array(int no1, int ****a)
{
*a = (int***)xmalloc(no1 * sizeof(int**));
if (*a == 0)
return 0;
for (int l = 0; l < no1; l++)
{
if (((*a)[l]=(int**)xmalloc((no1+1)*sizeof(int*))) == 0)
{
for (int l1 = 0; l1 < l; l1++)
free((*a)[l1]);
free(*a);
*a = 0;
return 0;
}
}
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
if (((*a)[l][h]=(int*)xmalloc(2*sizeof(int))) == 0)
{
/* Release prior items in current (partial) row */
for (int h1 = 0; h1 < h; h1++)
free((*a)[l][h1]);
/* Release items in prior (complete) rows */
for (int l1 = 0; l1 < l; l1++)
{
for (int h1 = 0; h1 < no1; h1++)
free((*a)[l1][h1]);
}
/* Release entries in first (complete) level of array */
for (int l1 = 0; l1 < no1; l1++)
free((*a)[l1]);
free(*a);
*a = 0;
return 0;
}
}
}
for (int l = 0; l < no1; l++)
for (int h = 0; h < no1; h++)
for (int k = 0; k < 2; k++)
(*a)[l][h][k] = 10000 * l + 100 * h + k;
return *a;
}
static void destroy_3d_array(int no1, int ***a)
{
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
free(a[l][h]);
free(a[l]);
}
free(a);
}
}
static void test_allocation(int no1)
{
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
for (int k = 0; k < 2; k++)
{
if (a[l][h][k] != l * 10000 + h * 100 + k)
printf("a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
}
}
}
}
destroy_3d_array(no1, a);
}
int main(int argc, char **argv)
{
int no1 = 5;
int fail_limit = 33;
if (argc == 2)
fail_limit = atoi(argv[1]);
for (fail_after = 0; fail_after < fail_limit; fail_after++)
{
printf("Fail after: %d\n", fail_after);
num_allocs = 0;
test_allocation(no1);
}
return 0;
}
Version 4 — Fewer memory allocations
Update 2014-12-20
The code above makes a lot of memory allocations, which complicates the release and error recovery. Here is an alternative version that makes just 3 allocations, one for the vector of pointers to pointers, one for the array of pointers, and one for the array of integers. It then sets the pointers to point to the correct places in memory.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
static int fail_after = 0;
static int num_allocs = 0;
static void *xmalloc(size_t size)
{
if (fail_after > 0 && num_allocs++ >= fail_after)
{
fputs("Out of memory\n", stdout);
return 0;
}
return malloc(size);
}
static int ***allocate_3d_array(int no1, int ****a)
{
int ***d0 = (int***)xmalloc(no1 * sizeof(int**));
int **d1 = (int **)xmalloc(no1 * no1 * sizeof(int *));
int *d2 = (int *)xmalloc(no1 * no1 * 2 * sizeof(int));
if (d0 == 0 || d1 == 0 || d2 == 0)
{
free(d0);
free(d1);
free(d2);
*a = 0;
return 0;
}
for (int l = 0; l < no1; l++)
{
d0[l] = &d1[l * no1];
for (int h = 0; h < no1; h++)
{
d0[l][h] = &d2[(l * no1 + h) * 2];
for (int k = 0; k < 2; k++)
d0[l][h][k] = l * 10000 + h * 100 + k;
}
}
*a = d0;
return *a;
}
static void destroy_3d_array(int ***a)
{
if (a != 0)
{
free(a[0][0]);
free(a[0]);
free(a);
}
}
static void test_allocation(int no1)
{
int ***a = 0;
int ***b = allocate_3d_array(no1, &a);
const char *pad[] = { " ", "\n" };
assert(b == a);
if (a != 0)
{
for (int l = 0; l < no1; l++)
{
for (int h = 0; h < no1; h++)
{
for (int k = 0; k < 2; k++)
{
if (a[l][h][k] != l * 10000 + h * 100 + k)
printf("Oops: a[%d][%d][%d] = %.6d%s", l, h, k, a[l][h][k], pad[k]);
}
}
}
}
destroy_3d_array(a);
}
int main(int argc, char **argv)
{
int no1 = 5;
int fail_limit = 4;
if (argc == 2)
fail_limit = atoi(argv[1]);
for (fail_after = 0; fail_after < fail_limit; fail_after++)
{
printf("Fail after: %d\n", fail_after);
num_allocs = 0;
test_allocation(no1);
}
return 0;
}
This has a clean bill of health with GCC 4.9.1 on Mac OS X 10.10.1, checked with valgrind version valgrind-3.11.0.SVN (built from an SVN tree with some necessary fixes for Mac OS X, but not enough suppressions).
The diagnostic print (starting with 'Oops') was triggered while I developed the answer; I had my pointer calculations wrong at the time.
Sorry, but, to be blunt: this is a horrid way of handling a 3D array: a double-nested loop with a bucketload of calls to malloc(), then triple-indirection to get a value at runtime. Yeuch! :o)
The conventional way of doing this (in the HPC community) is to use a one-dimensional array and do the index computation yourself. Suppose index i iterates over nx planes in the x direction, j iterates over ny pencils in the y direction, and k iterates over nz cells in the z direction. Then a pencil has nz elements, a plane has nz*ny elements, and the whole “brick” has nz*ny*nx elements. Thus, you can iterate over the whole structure with:
for(i=0; i<nx; i++) {
for(j=0; j<ny; j++) {
for(k=0; k<nz; k++) {
printf("a(%d,%d,%d) = %d\n", i, j, k, a[(i*ny+j)*nz+k]);
}
}
}
The advantage of this construction is that you can allocate it with a single call to malloc(), rather than a boatload of nested calls:
int *a;
a = malloc(nx*ny*nz*sizeof(int));
The construction x=a[i][j][k] has three levels of indirection: you have to fetch an address from memory, a, add an offset, i, fetch that address from memory, a[i], add an offset, j, fetch that address from memory, a[i][j], add an offset, k, and (finally) fetch the data, a[i][j][k]. All those intermediate pointers are wasting cache-lines and TLB entries.
The construction x=a[(i*ny+j)*nz+k] has one level of indirection at the expense of two additional integer multiplications: compute the offset, fetch address, 'a', from memory, compute and add the offset, (i*ny+j)*nz+k, fetch the data.
Furthermore, there is essentially no way whatsoever of improving the triple-indirection method's performance based on data-access patterns. If we were actually visiting every cell, we could do something like this to avoid some of the overhead of index computation.
ij = 0;
for(i=0; i<nx; i++) {
ii=i*ny;
for(j=0; j<ny; j++) {
ij=(ii+j)*nz;
for(k=0; k<nz; k++) {
printf("a(%d,%d,%d) = %d\n", i, j, k, a[ij+k]);
}
}
}
Depending on what you're doing, this may not be great either, and there all alternative layouts and indexing methods (such as Morton or Ahnenteufel indexing) that may be more suitable, depending on your access patterns. I'm not trying to give a complete treatise on 3D Cartesian grid representation or indexing, merely illustrate that a “three star” solution is very bad for numerous reasons.
By using (*a)[l][h][0] you are trying to de-reference a plain int and not a pointer.
use a[l][h][0] directly to assign any value to it.

why I am getting this result in last half of array?

Can anyone tell me why the output ( Anew ) is:
Anew = 0.000000
Anew = 2.000000
Anew = 4.000000
Anew = 6.000000
Anew = 16.000000
Anew = 20.000000
Anew = 24.000000
Anew = 28.000000
and not :
Anew = 0.000000
Anew = 2.000000
Anew = 4.000000
Anew = 6.000000
Anew = 8.000000
Anew = 10.000000
Anew = 12.000000
Anew = 14.000000
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mkl.h>
int main(int argc, const char* argv[]) {
int rows = 2, cols = 2, Layers = 2;
int PerLayerElmts = rows * cols;
float* A = malloc(PerLayerElmts * Layers * sizeof(*A));
// create A matrix
int ImagIdx;
for (int n = 0; n < Layers; n++) {
ImagIdx = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
A[n * PerLayerElmts + ImagIdx] = n * PerLayerElmts + ImagIdx;
ImagIdx++;
}
}
}
// print A matrix
for (int n = 0; n < Layers; n++) {
ImagIdx = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("\nA = %f", A[n * PerLayerElmts + ImagIdx]);
ImagIdx++;
}
}
}
float scalar = 2.0;
size_t AddressOffset = 0;
for (int i = 0; i < Layers; i++, AddressOffset += PerLayerElmts) {
// multiply A by scalar
cblas_sscal(PerLayerElmts * Layers, scalar, A + AddressOffset, 1);
}
// print A matrix
for (int n = 0; n < Layers; n++) {
ImagIdx = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("\n\nAnew = %f", A[n * PerLayerElmts + ImagIdx]);
ImagIdx++;
}
}
}
printf("\n");
free(A);
return 0;
}
I am just creating a matrix and then using cblas call to multiply every element by a scalar ( 2 ).
I am doing that , using an addressoffset for the number of layers.
The problem is at the second layer where the elements are multiply by 4 and not 2!
Your way of calling cblas_sscal doesn't seem right. Instead of
cblas_sscal( PerLayerElmts * Layers , scalar , A + AddressOffset , 1 );
I would expect something like
cblas_sscal( PerLayerElmts , scalar , A + AddressOffset , 1 );
since you're calling it once for every layer.

Resources