全部用炼金术打破? [英] globals broken with alchemy?

查看:204
本文介绍了全部用炼金术打破?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Adob​​e Alchemy 似乎没有运行全局构造函数。这里有一些简单的测试代码:

  #include< stdio.h> 
$ b $ class TestClass {
public:
TestClass(const char message []){
printf(hello%s \\\
,message);
}
};

TestClass global(global);
$ b $ int main(int argc,char ** argv){
TestClass local(local);
printf(in main \\\
);
返回0;



$ b当使用本地gcc编译时,它会输出:

  hello global 
hello local
in

使用gcc编译时,输出:

  hello local 
in main

这个问题打破了很多代码,特别是 UnitTest ++ (这取决于全局变量初始化,使其自动测试列表功能工作)。

d真的很想深究这一点。这是一个错误还是一个功能,只是没有及时实施发布?是否可以解决方法?



编辑:Adobe论坛的相关文章是

也遇到了同样的问题。据我所知,这似乎是这样的:

类型的每个静态和全局变量将默默无法初始化,如果甚至一个单个类尝试在其初始化过程中的任何时候进行动态分配。可能这是因为用于动态内存的ByteBuffer尚不可用。我希望炼金术会更清楚地说明它的错误信息,因为现在它就像是一串旧时的圣诞灯,一个死灯泡会引起整个链条的关闭。



对于解决方法,一旦您发现有问题的对象,您需要以某种方式将其初始化延迟到运行时。这三种技术都是指针,懒惰的评估函数,或者是用新的放置位置初始化的缓冲区的引用。

指针

  //`全局`现在是一个指针
TestClass * global;

//所有全局变量初始化现在在这里被找到$ b $ void init_globals(){
global = new TestClass(global);


int main(int argc,char ** argv){
//这需要在开始时显式调用Alchemy
init_globals();

然后,您需要重构代码,更改每个出现的全局 to (* global)



功能

  //`全局`现在是一个函数
TestClass& global(){
//静态局部变量被初始化,当它们的函数被第一次调用时$ b $静态变量TestClass global _(global);
return global_;



$ b现在你需要将每一个出现的全局 global()。值得注意的是,这是这三种技术中唯一不需要显式调用 init_globals 的唯一方法。在这种情况下,除非名称更改为 global()是麻烦的,否则我推荐这种方式:



<一个内存缓冲区被创建得足够大以容纳一个TestClass对象

$ pre $ b $ b unsigned char global_mem [sizeof(TestClass)];
//``全球`现在是一个参考。
TestClass& global = *(TestClass *)(void *)global_mem;

void init_globals(){
//这将在我们的内存缓冲区中初始化一个新的TestClass对象$ b $ new(global_mem)TestClass(global);


int main(int argc,char ** argv){
init_globals();

这种方法的优点是您不需要更改任何其他代码,如 global 仍然被称为 global 。不幸的是,维护一个 init_globals 函数可能会很麻烦。




编辑: b $ b在后面的问题中发现,除了动态分配之外,包含静态局部函数的函数在Alchemy初始化期间也不能被调用。


It seems that Adobe Alchemy isn't running global constructors. Here's some simple test code:

#include <stdio.h>

class TestClass {
public:
    TestClass(const char message[]) {
        printf("hello %s \n", message);
    }
};

TestClass global("global");

int main(int argc, char **argv) {
    TestClass local("local");
    printf("in main\n");
    return 0;
}

When compiled with native gcc it outputs:

hello global
hello local
in main

When compiled with alchemy gcc it outputs:

hello local
in main

This problem breaks lots of code, notably UnitTest++ (which depends on globals getting initialized to make its auto test-list functionality work).

I'd really like to get to the bottom of this. Is it a bug or a feature that just didn't get implemented in time for the release? Is it possible to workaround?

EDIT: A relevant post on the Adobe Forums is here.

解决方案

I've run into the same problem. As far as I could tell, this seems to be the case:

Every single static and global variable of class type will silently fail to be initialized if even a single class attempts dynamic allocation at any point during its initialization. Presumably this is because the ByteBuffer being used for dynamic memory isn't yet available. I wish Alchemy would be more clear with its error messages, because at the moment it's like a strand of old-timey Christmas lights where one dead bulb would cause the entire strand to shut off.

For a workaround, once you've discovered the offending object, you'll need to somehow defer its initialization to runtime. The three techniques that come to mind are pointers, lazy evaluation functions, or references to buffers initialized with placement new.

Pointers

// `global` is now a pointer
TestClass *global;

// all global variable initialization is found here now
void init_globals() {
  global = new TestClass("global");
}

int main(int argc, char **argv) {
  // this needs to be explicitly called at the start Alchemy
  init_globals();

You'll then need to refactor your code, changing every occurence of global to (*global).

Function

// `global` is now a function
TestClass& global() {
  // static locals are initialized when their functions are first called
  static TestClass global_("global");
  return global_;
}

Now you need to replace every occurence of global with global(). Notably, this is the only one of these three techniques that doesn't require an explicit init_globals call. I recommend this way unless the name changing to global() is troublesome for some reason... in which case:

Placement new

// a memory buffer is created large enough to hold a TestClass object
unsigned char global_mem[sizeof(TestClass)];
// `global` is now a reference.  
TestClass& global = *(TestClass*)(void*)global_mem;

void init_globals() {
  // this initializes a new TestClass object inside our memory buffer
  new (global_mem) TestClass("global");
}

int main(int argc, char **argv) {
  init_globals();

The advantage of this approach is you don't need to change any other code, as global is still just called global. Unfortunately, maintaining an init_globals function can be troublesome.


Edit:
As discovered in a later question, in addition to dynamic allocation, functions containing static locals also cannot be called during Alchemy's initialization.

这篇关于全部用炼金术打破?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆