const argument changes after array definition - c

I have what I consider a really strange problem. I have a function with the following prototype:
void generateNodes(const int maxX, const int maxY, node nodes[]);
As one of the first things in this function I define a 2d array of shorts, which i use as boolean values. But when I call this function the value of maxY changes to a large value. The code in question is below:
void generateNodes(const int maxX, const int maxY, node nodes[]){
int i, currentX, currentY;
short used[MAX_NODES][MAX_NODES];
//Generate the nodes
for(i = 0; i < MAX_NODES; i++){
currentX = randomNumber(0,maxX);
currentY = randomNumber(0,maxY);
nodes[i].color = 0;
nodes[i].numberOfConnections = 0;
nodes[i].id = i;
nodes[i].distanceFromStart = NOT_SET;
nodes[i].parent = NULL;
if(!used[currentX][currentY]){
nodes[i].x = currentX;
nodes[i].y = currentY;
used[currentX][currentY] = 1;
} else {
i--;
}
}
int numberOfConnections, j, currentNeighbor;
//Generate the connections
for(i = 0; i < MAX_NODES; i++){
numberOfConnections = randomNumber(1,5); //Between one and five outgoing connections
for(j = 0; j < numberOfConnections; j++){
currentNeighbor = randomNumber(0,19); //Select the neighbor
while(currentNeighbor == i){
currentNeighbor = randomNumber(0,19); //Try again while the selected is self
}
nodes[i].canReach[++(nodes[i].numberOfConnections)] = &nodes[currentNeighbor];
nodes[currentNeighbor].canReach[++(nodes[currentNeighbor].numberOfConnections)] = &nodes[i];
}
}
}
MAX_NODES is defined to 20.
Does anyone know why this might happen?

Very probably the code in ... is accessing beyond the end of used, causing arguments to be smashed. Without the code, it's of course impossible to say.

Since you do not seem to initialize the array used, it may well be that some elements are considered used (!= 0), since an array on stack is not initialized to zero, but takes whatever was in that memory area before.
An if an X,Y pair is considered used, you decrement the loop counter, possibly beyond zero into the negative realm, possibly overwriting - on the next iteration - part of the stack. This may also change the parameters, since they also reside on the same stack, before the local array.
Start with initializing used, and consider rewriting the loop to not change the loop variable except in the for statement.

Related

Need help understanding logic of function

monthly->maxTemperature = yearData[i].high;
monthly->minTemperature = yearData[i].low;
I just can't seem to understand the logic of what the iterations will look like or how to access the proper elements in the array of data to get the proper data for each month.... without corrupting data. Thanks!
You're on the right track:
void stats(int mth, const struct Data yearData[], int size, struct Monthly* monthStats)
{
// These are used to calc averages
int highSum = 0;
int lowSum = 0;
int days = 0;
// Initialize data
monthly->maxTemperature = INT_MIN;
monthly->minTemperature = INT_MAX;
monthly->totalPrecip = 0;
for (int i = 0; i < size; ++i) {
// Only use data from given month
if (yearData[i].month == mth) {
days += 1;
if (yearData[i].high > monthly->maxTemperature) monthly->maxTemperature = yearData[i].high;
if (yearData[i].low < monthly->minTemperature) monthly->minTemperature = yearData[i].low;
highSum += yearData[i].high;
lowSum + yearData[i].low;
monthly->totalPrecip += yearData[i].precip;
}
}
if (0 != days) {
monthly->avgHigh = highSum / days;
monthly->avgLow = lowSum / days;
}
}
Before working on the assignment it's a good idea to examine the API that you need to implement for clues. First thing to notice is that the reason the struct Monthly is passed to your function by pointer is so that you could set the result into it. This is different from the reason for passing struct Data as a pointer*, which is to pass an array using the only mechanism for passing arrays available in C. const qualifier is a strong indication that you must not be trying to modify anything off of the yearData, only the monthStats.
This tells you what to do with the min, max, average, and total that you are going to find in your function: these need to be assigned to fields of monthStats, like this:
monthStats->maxTemperature = maxTemperature;
monthStats->minTemperature = minTemperature;
...
where maxTemperature, minTemperature, and so on are local variables that you declare before entering the for loop.
As far as the for loop goes, your problem is that you ignore the mth variable completely. You need to use its value to decide if an element of yearData should be considered for your computations or not. The simplest way is to add an if to your for loop:
int maxTemperature = INT_MIN; // you need to include <limits.h>
int minTemperature = INT_MAX; // to get definitions of INT_MIN and INT_MAX
for(int i = 0; i<size; ++i) {
if (yearData[i].month < mth) continue;
if (yearData[i].month > mth) break;
... // Do your computations here
}
* Even though it looks like an array, it is still passed as a pointer

Segmentation fault (core dumped) error, in a C search function

I'm trying to write a C program to take an array of discrete positive integers and find the length of the longest increasing subsequence.
'int* a' is the array of randomly generated integers, which is of length 'int b'
call:
lis_n = answer(seq, seq_size);
function:
int answer(int* a, int b) {
if (a == NULL) {return -1;}
int i = 0;
int j = 0;
int k = 0;
//instantiate max and set it to 0
int max = 0;
//make an array storing all included numbers
int included[b];
memset(included, 0, b*sizeof(int));
//create a pointer to the index in included[] with the largest value
int indexMax = 0;
//create a pointer to the index in a[]
int indexArray = 0;
//index of a[] for max included
int maxToA = 0;
//set the first included number to the first element in a[]
included[indexMax] = a[indexArray];
//loop until break
while (1) {
if (a[indexArray] > included[indexMax]/*digit greater than last included*/) {
//include the digit
included[indexMax+1] = a[indexArray];
//increment current max pointer
indexMax++;
}
j = b - 1;
while (indexArray >= j/*pointer is at end"*/) {
if (j == (b - 1)) {
if ((indexMax+1) > max/*total is greater than current max*/) {
max = indexMax + 1;
}
}
if (a[b-1] == included[0]/*last element is in included[0], stop*/) {
return max;
} else {
//max included is set to zero
included[indexMax] = 0;
//max included pointer decreased
indexMax--;
//set array pointer to new max included
for (k=0;k<(b-1);k++) {
if (a[k] == included[indexMax]) {
indexArray = k;
}
}
//increment array pointer
indexArray++;
j--;
}
}
indexArray++;
printf("(");
for (i=0;i<b;i++) {
printf("%d,",included[i]);
}
printf(")");
}
}
I'm receiving 'Segmentation fault (core dumped)' in the terminal upon running.
Any help would be awesome.
You have declared
int indexMax = 0;
And here you use it as an array index
incuded[indexMax] = 0;
You increment and decrement it
indexMax++;
...
indexMax--;
You check its range but you don't limit it, you alter the value you compare it with
if ((indexMax+1) > max/*total is greater than current max*/) {
max = indexMax + 1;
}
You never check indexMax against b or with 0
int included[b];
So you are almost guaranteed to exceed the bounds of included[].
Some general points of advice. Make your function and variable names meaningful. Avoid making a premature exit from a function wherever possible. Avoid while(1) wherever possible. And never make assumptions about array sizes (including C "strings"). It might seem hard work putting in the overhead, but there is a payoff. The payoff is not just about catching unexpected errors, it makes you think about the code you are writing as you do it.
I've done something like this for homework before. I got help from:
https://codereview.stackexchange.com/questions/30491/maximum-subarray-problem-iterative-on-algorithm
Make sure you are not trying to index past the size of your array. What I would do would be to find out the size of array a[] (which looks like it is b) and subtract 1. Make sure you are not trying to access past the size of the array.

Pass 2d array in function - return 2d array from a function in C

So i have read the other threads but i cant figure it out. My code is the following and it works fine.
double **sort(int counter, double **a){
int i, j;
double swap0, swap1;
for (i = 0 ; i < ( counter - 1 ); i++){
for (j = 0 ; j < counter - i - 1; j++){
if (a[0][j] > a[0][j+1]){
swap0 = a[0][j];
swap1 = a[1][j];
a[0][j] = a[0][j+1];
a[1][j] = a[1][j+1];
a[0][j+1] = swap0;
a[1][j+1] = swap1;
}
}
}
return a;
}
main(){
double **dist_table;
int i;
dist_table = (double **)calloc(2,sizeof(double*));
dist_table[0] = (double *)calloc(5,sizeof(double));
dist_table[1] = (double *)calloc(5,sizeof(double));
dist_table[0][0] = 5.1;
dist_table[1][0] = 0;
dist_table[0][1] = 6.1;
dist_table[1][1] = 1;
dist_table[0][2] = 3.1;
dist_table[1][2] = 2;
dist_table[0][3] = 2.1;
dist_table[1][3] = 3;
dist_table[0][4] = 7.1;
dist_table[1][4] = 4;
dist_table = sort(5, dist_table);
}
BUT i read that passing as an argument the **a is wrong. So why my codes runs fine, and which would be the right way?
Your function is just returning the same pointer you passed to it. Replacing:
dist_table = sort(5, distortable);
with:
sort(5, distortable);
would generally be better in this case, although sometimes returning the same value can be useful (e.g. if you want to use it within a larger expression).
For the last part of your question, passing a double ** would be wrong if you actually had a two-dimensional array of doubles, like this:
double my_array[2][5];
but that isn't what you have. You have a one-dimensional (dynamically allocated) array of double *, each element of which points to a one-dimensional (dynamically allocated) array of double. Actual multi-dimensional arrays are represented differently in memory to this, which is why passing a double ** would not work. But what you actually have here is completely different, and passing a double ** is fine, here.
Other unrelated points...
Casting the return from calloc() is completely unnecessary, and generally considered bad form. Better would be:
dist_table = calloc(2,sizeof(double*));
dist_table[0] = calloc(5,sizeof(double));
dist_table[1] = calloc(5,sizeof(double));
or better still:
dist_table = calloc(2,sizeof *dist_table);
for ( int i = 0; i < 2; ++i ) {
dist_table[i] = calloc(5,sizeof *(dist_table[i]));
}
Don't forget to check the return value of calloc() to find out if the allocation succeeded.
As long as you know the depth of the array and elements size you're doing it the right way.
Consider null terminating the array if the number of elements are dynamic and not limited to two.

Function Warnings in C

Hello guys i have threefunctions for which i get 4 warnings...!!
The first one is this
void evaluatearxikos(void)
{
int mem;
int i;
double x[NVARS+1];
FILE *controlpointsarxika;
controlpointsarxika = fopen("controlpointsarxika.txt","r");
remove("save.txt");
for(mem = 0; mem < POPSIZE; mem++)
{
for(i = 0; i < NVARS; i++)
{
x[i+1] = population[mem].gene[i];
}
rbsplinearxiki();
XfoilCall();
population[mem].fitness = FileRead();
remove("save.txt");
}
fclose(controlpointsarxika);
}
For this one the compiler warns me tha variable x is set but not used...!! But actually i am using the variable x...!!!
The second function is this one...
void elitist(void)
{
int i;
double best,worst;
int best_mem,worst_mem;
best = population[0].fitness;
worst = population[0].fitness;
for(i = 0; i < POPSIZE - 1; i++)
{
if(population[i].fitness > population[i+1].fitness)
{
if(population[i].fitness >= best)
{
best = population[i].fitness;
best_mem = i;
}
if(population[i+1].fitness <= worst)
{
worst = population[i+1].fitness;
worst_mem = i+1;
}
}
else
{
if(population[i].fitness <= worst)
{
worst = population[i].fitness;
worst_mem = i;
}
if(population[i+1].fitness >= best)
{
best = population[i+1].fitness;
best_mem = i+1;
}
}
}
if(best >= population[POPSIZE].fitness)
{
for(i = 0; i < NVARS; i++)
{
population[POPSIZE].gene[i] = population[best_mem].gene[i];
}
population[POPSIZE].fitness = population[best_mem].fitness;
}
else
{
for(i = 0; i < NVARS; i++)
{
population[worst_mem].gene[i] = population[POPSIZE].gene[i];
}
population[worst_mem].fitness = population[POPSIZE].fitness;
}
}
For this one i get two warnings that the variables worst_mem and best_mem may be used uninitialized in this function..!! But i initialize values to both of them..!!
And the third function is this...
void crossover(void)
{
int mem,one;
int first = 0;
double x;
for(mem =0; mem < POPSIZE; mem++)
{
x = rand()%1000/1000;
if(x < PXOVER)
{
first++;
if(first%2 == 0)
{
random_Xover(one,mem);
}
else
{
one = mem;
}
}
}
}
For which i get that the variable one may be used unitialized..!! But it is initialized..!
Can you please tell me what is wrong with these functions...??
Thank you in advance
In your first function, you set (assign) x, but you never read it, hence you are not using it... you're only wasting CPU cycles by writing to it. (Note also that because you index it as i+1 you write beyond the space you've allocated for it).
In the second function, your initializations to those variables are in conditional blocks. You can see that (perhaps? I didn't verify) in all conditions they are initialized but your compiler isn't that smart.
In your third function, it does appear that one could be refered to without having first been initialized.
First: You set x but do not use it. It's a local variable that gets set but it's dropped as soon as the function returns.
Second: There might be values that makes it so that your best_mem/worst_mem never gets set in your if/else, but you are using them later on. If they haven't been set, they contain garbage if not initialized.
Third: While it shouldn't happen that you try to use an uninitialized variable in your code, it still looks weird and compiler doesn't see that it won't happen first time.
When you get compiler warnings, treat is as you are doing something wrong or rather not recommended and that it could be done in a better way.
The x variable is only used on the left hand side (i.e. assigned a value). You are not using that value on the right hand side or pass it to a function.
It may be possible to get to the end of the loop for(i = 0; i < POPSIZE - 1; i++) without those variables given a value. Why not set them in the declaration.
The call to random_Xover(one,mem); could be called when one is not set. Change the line int mem,one; to int mem,one = <some value>;

Struct Array initialization in c

typedef struct _set{
int root;
int rank;
}Set;
void Kruskal(Graph* g)
{
Set uni[g->nv];
Edge result[g->nv - 1];
int i;
int count = 0;
int num = 0;
int aRoot, bRoot;
for(i = 0; i < g->nv; i++){
uni[i].root = i;
uni[i].rank = 0;
}
QuickSort(g, 0, g->ne-1);
while(count != (g->nv-1) && num != g->ne){
WeightedUnion(uni, g->path[num].src, g->path[num].dest);
aRoot = Find(uni, g->path[num].src);
bRoot = Find(uni, g->path[num].dest);
if( aRoot != bRoot){
result[num] = g->path[num];
count++;
}
num++;
}
if(count != g->nv-1){
printf("No spanning tree\n");
}
else{
for(i = 0; i <= count; i++){
printf("[%d] %d - %d : %d\n",i+1,result[i].src,result[i].dest,result[i].weight);
}
}
}
This is my part of code. The problem is that I can't initialize 'uni[g->nv]'. You can see 'for' loop next to the variable area. And I was sure about that reputation must initialize this array but a result was not. That array didn't include any other values. just empty. I cannot find my problem. Please tell me my problem or mistakes.
I run my code in Xcode. Maybe this information is helpful
You are using a variable length array (VLA), that is an array with a length that depends dynamically on an expression during run time. Since the size is not known at compile time, you can't initialize them with an initializer expression, but must do it with a for loop as you are doing.
VLA are usually realized when your program executes on the so-called stack of the function in which it is defined. That stack has a size limit and you have to be careful that you don't overrun it. (And if you do, there is no tool to know directly.)
So don't use VLA as you do for big data of unknown size. Instead, use a pointer and malloc to allocate the memory that you need.

Resources