C语言equivalent用法,大约在VC中相当于c:__ attribute __((constructor))吗?

这篇博客探讨了如何在Visual C++ (VC) 中模仿GCC中的C构造函数功能。作者提供了针对VC和GCC的宏定义,使得在C程序中能够实现在程序加载时自动调用的初始化函数。文章提到了VC中关于__attribute__((constructor))的不支持,并给出了解决方案,包括使用.CRT$XCU段和DllMain。同时,还讨论了在MSVC中禁用全局优化以避免构造函数优化问题。
摘要由CSDN通过智能技术生成

我想知道是否可以在VC中使用C构造函数,就像在GCC中使用它们一样。

使用__attribute__关键字的gcc方法非常简单,不幸的是VC似乎甚至都不知道这个关键字,因为我不是Win32程序员,所以我想知道是否存在某种等效的关键字。

请注意-这是一个C程序,甚至不是C ++或C#(因为用这些语言很容易做到)

对于那些还没有使用过它的人,它有什么作用? (您需要它做什么?)

动态链接器在加载对象时会运行任何标记为constructor的函数。

@:Jalf:属性构造函数的工作原理是什么?

下面的C代码演示了如何定义在main执行之前在程序/库加载时调用的void(void)函数。

对于MSVC,这会将指针指向用户初始化程序部分(.CRT $ XCU)中的函数,与编译器为构造函数调用静态C ++对象所做的基本相同。 对于GCC,使用构造函数属性。

// Initializer/finalizer sample for MSVC and GCC/Clang.

// 2010-2016 Joe Lowe. Released into the public domain.

#include

#include

#ifdef __cplusplus

#define INITIALIZER(f) \

static void f(void); \

struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \

static void f(void)

#elif defined(_MSC_VER)

#pragma section(".CRT$XCU",read)

#define INITIALIZER2_(f,p) \

static void f(void); \

__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \

__pragma(comment(linker,"/include:" p #f"_")) \

static void f(void)

#ifdef _WIN64

#define INITIALIZER(f) INITIALIZER2_(f,"")

#else

#define INITIALIZER(f) INITIALIZER2_(f,"_")

#endif

#else

#define INITIALIZER(f) \

static void f(void) __attribute__((constructor)); \

static void f(void)

#endif

static void finalize(void)

{

printf("finalize

");

}

INITIALIZER( initialize)

{

printf("initialize

");

atexit( finalize);

}

int main( int argc, char** argv)

{

printf("main

");

return 0;

}

嗨乔:很棒的帖子!我真的需要使用VC的技巧。在C(而非C ++)中自动注册单元测试功能至关重要。顺便说一句:宏INITIALIZER的第二行中应该有一个结尾

这样的构造器将在新的Visual Studio版本中进行优化。它是众所周知的,不幸的是尚未解决的错误。到目前为止,我发现的唯一解决方法是:必须禁用项目属性> C / C ++>优化>整个程序优化(/ GL)。

我遇到了与上述相同的问题,因此请不要在上面粘贴复制代码(假设它可以正常工作)。

由于以下原因,GLib最近从使用.CRT$XCU部分切换为使用DllMain:bugzilla.gnome.org/show_bug.cgi?id=752837

@ user3042599。感谢您对MSVC 2015链接时间优化问题的注意。我已经编辑了代码示例,并且应该没有问题,尽管由于使用__pragma(),现在它需要MSVC 2008或更高版本。

嗨,很抱歉,要恢复旧线程...我也遇到同样的问题,该函数是:`void __attribute __((constructor))init(){//设置GPU内存管理cuda :: gpu_mat_allocator = new cuda :: Allocator( ); // cv :: cuda :: GpuMat :: setDefaultAllocator(cuda :: gpu_mat_allocator); }`我将上面的示例用于:`INITIALIZER(initialize){cuda :: gpu_mat_allocator = new cuda :: Allocator(); atexit(完成); }`正确吗?

我认为没有办法避免在MSVC中使用C ++功能。 (MSVC的C支持仍然很糟糕。)

未经测试,但这至少应允许相同的代码在MSVC和GCC中都能工作。

#if defined(_MSC_VER)

struct construct { construct(void (*f)(void)) { f(); } };

#define constructor(fn) \

void fn(void); static constructor constructor_##fn(fn)

#elif defined(__GNUC__)

#define constructor(fn)

void fn(void) __attribute__((constructor))

#endif

static constructor(foo);

void foo() {

...

}

据我所知,这不适用于MSVC 2013或2015上的纯C。似乎C编译器模式不支持结构中的构造函数。我试图使它以各种方式工作。

您可能对DllMain感兴趣。

它必须在输入main()之前执行,多数民众赞成在dll中,这有何关系? :/

人们对__attribute __((constructor))唯一真正的用途是在共享库中使用它们,就像模拟DllMain :)

__attribute__((constructor))即使在单个程序映像中也很有用;例如,在库和系统调用周围插入全局挂钩,或注册内置的"插件",或初始化动态链接的模块在其" DllMain"中均需要的数据结构。

我在MSVC中尝试了最后一个答案

#ifdef _MSC_VER

#pragma section(".CRT$XCU",read)

#define INITIALIZER2_(f,p) \

static void f(void); \

__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \

__pragma(comment(linker,"/include:" p #f"_")) \

static void f(void)

#ifdef _WIN64

#define INITIALIZER(f) INITIALIZER2_(f,"")

#else

#define INITIALIZER(f) INITIALIZER2_(f,"_")

#endif

#else

#define INITIALIZER(f) \

static void f(void) __attribute__((constructor)); \

static void f(void)

#endif

但INITIALIZER(f)不能出现在两个具有相同函数名传递给INITIALIZER的文件中,以下定义将允许

#ifdef _MSC_VER

#define INITIALIZER(f) \

static void f();\

static int __f1(){f();return 0;}\

__pragma(data_seg(".CRT$XIU"))\

static int(*__f2) () = __f1;\

__pragma(data_seg())\

static void f()

#else

#define INITIALIZER(f) \

__attribute__((constructor)) static void f()

#endif

我的答案中的链接器编译指示是必需的,并且确实具有初始化程序函数名称对于整个exe / dll必须唯一的效果。请参阅user3042599在我的示例下的评论以及我的回复。我不知道节名称的更改是否是链接器编译指示的替代解决方案,但是它将带来其他副作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值