【问题标题】:Initializer element is not constant when trying to declare a global struct尝试声明全局结构时,初始值设定项元素不是常量
【发布时间】:2018-10-10 05:55:11
【问题描述】:

我目前是一名 Java 程序员,在 C 语言中为一个类做一些工作,我一直在努力解决两者之间的差异。目前,我正在尝试使用编译器挂钩添加功能,以计算在正在执行的程序的每个函数中花费的时间。我对此的斗争是我的解决方案是使用堆栈,并且我无法实例化(如果这甚至是正确的词?)堆栈,因为我无法添加 main 方法或类似的东西来创建一开始。这是我现在的代码:

#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);

}

现在,当我尝试编译此代码时,我在创建 entry_times 堆栈的行中收到“初始化器元素不是常量”错误点。如何解决此错误,或重构我的代码以防止出现此问题?

很抱歉,如果这是一个重复的主题,我已经进行了大量搜索,但我怀疑我根本不知道要实际搜索什么才能找到我正在寻找的信息。

【问题讨论】:

  • @Someprogrammerdude:OP 并没有发明那些双下划线名称——它们是由实现决定的名称。所以一切都很好。
  • @JohnZwinck 我实际上认为我已经看过其中一个了-如果我错了请纠正我,但似乎这些建议有两种解决方案:1)我可以有一个初始化方法,或者 2)我可以使用#define 使其成为常数。我正在努力理解如何将这些中的任何一个应用于这个特定场景,因为我认为我不能为编译器 prehook 提供一个 init 方法?而且我似乎无法理解如何使用#define 创建结构,我花了最后半个小时试图做到这一点,但没有成功。
  • 也许您正在寻找 C++ — 它允许您在全局范围内的初始化程序中使用函数。
  • 既然您已经在使用 GCC 特定的构造 (__attribute__),那么也许要创建一个“构造器”函数,该函数将在 main 之前调用并且可以进行任何您需要的初始化?有关更多信息,请参阅this list of common function attributes

标签: c


【解决方案1】:

John Zwinck 的链接中解释了您收到错误的原因,但如何为您解决问题取决于您。您可以创建为您进行初始化的构造函数,例如

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

或者你可以围绕它创建一个包装函数

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

并在代码中使用my_entry_times() 而不是entry_times

【讨论】:

  • 第一个解决方案对我有用!非常感谢!
【解决方案2】:

在 C 语言中,在文件或全局范围内初始化变量时不能调用函数。

您应该调用malloc 为您分配一些内存,如下所示:

static stack_t* entry_times = NULL;

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

这将为您提供 500 个 stack_t 实例。

当你不再需要内存时,你需要free

编辑:

这是我对您的问题的解决方案 - 不是很漂亮,但如果您只有这两个功能,那么您会受到很大限制...

#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);

}

【讨论】:

  • 我认为要解决 OPs 问题(缺少初始化函数),您需要帮助设计执行 malloc() 调用的时间/位置。
  • 不幸的是,此解决方案似乎无助于解决问题...
猜你喜欢
  • 1970-01-01
  • 2016-06-03
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 2023-03-11
  • 2014-05-25
  • 1970-01-01
相关资源
最近更新 更多