katamaster818
katamaster818

Reputation: 341

Initializer element is not constant when trying to declare a global struct

I am currently a Java programmer doing some work in C for a class, and I've been struggling a lot with the differences between the two. Currently, I am trying to add functionality with compiler hooks to count the time that is spent within each function of the program that is being executed. My struggle for this is that my solution is to use a stack, and I'm having trouble instantiating (if that's even the right word to use?) the stack since I can't add a main method or something of that sort to create it at the beginning. Here is my code now:

#include <stdio.h>
#include <time.h>
#include "mystack.h"

static stack_t* entry_times=create_stack(500);
static unsigned int count_entered=0;
static unsigned int count_completed=0;


__attribute__((no_instrument_function))
void __cyg_profile_func_enter(void *this_fn, void *call_site){
    count_entered++;
    time_t start_time;
    time(&start_time);
    stack_enqueue(entry_times, start_time);
    printf("Total Functions Entered: %d\n", count_entered);

}

__attribute__((no_instrument_function))
void __cyg_profile_func_exit(void *this_fn, void *call_site){

    time_t end_time;
    time(&end_time);
    time_t start_time = stack_dequeue(entry_times);
    double difference = difftime(end_time, start_time);
    count_completed++;
    printf("Time in Function: %d\n", difference);

}

Right now, when I try to compile this code, I am getting a "initializer element is not constant" error point to the line where I create my entry_times stack. How can I solve this error, or refactor my code to prevent this issue?

I'm sorry if this is a duplicate topic, I have done a fair amount of searching, and I suspect I simply do not know what to actually search for to find the information that I am looking for.

Upvotes: 0

Views: 157

Answers (2)

Mindaugas
Mindaugas

Reputation: 1735

Why you are getting error is explained in John Zwinck's links, but how to solve it for you, it depends. You could create constructor function which does initialisation for you e.g.

static stack_t* entry_times;
__attribute__((constructor))
void my_init(){
    entry_times=create_stack(500);
}

or you could create a wrapper function around it

stack_t* my_entry_times(){
    static stack_t* entry_times;
    if (!entry_times) {
        entry_times=create_stack(500);
    }
    return entry_times;
}

and use my_entry_times() instead of entry_times in code

Upvotes: 3

NeRa
NeRa

Reputation: 101

In C you can't call a function when initialising a variable in file or global scope.

You should be calling malloc to allocate some memory for you, something like this:

static stack_t* entry_times = NULL;

entry_times = (stack_t*)malloc(500 * sizeof(stack_t));

That will give you 500 instances of stack_t.

You need to free when you no longer need the memory.

EDIT:

Here is my solution for your problem - not pretty but if you only have those two functions, you are quite restricted...

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mystack.h"

static stack_t* entry_times=NULL;
static unsigned int count_entered=0;
static unsigned int count_completed=0;


__attribute__((no_instrument_function))
void __cyg_profile_func_enter(void *this_fn, void *call_site){
    if (entry_times == NULL) {
        entry_times = (stack_t *)malloc(500 * sizeof(stack_t));
    }
    count_entered++;
    time_t start_time;
    time(&start_time);
    stack_enqueue(entry_times, start_time);
    printf("Total Functions Entered: %d\n", count_entered);

}

__attribute__((no_instrument_function))
void __cyg_profile_func_exit(void *this_fn, void *call_site){

    time_t end_time;
    time(&end_time);
    time_t start_time = stack_dequeue(entry_times);
    double difference = difftime(end_time, start_time);
    count_completed++;
    if (entry_times != NULL) {
        free(entry_times);
        entry_times = NULL;
    }
    printf("Time in Function: %d\n", difference);

}

Upvotes: 0

Related Questions