使用STL与炼金术 [英] using STL with Alchemy

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

问题描述

虽然Alchemy支持编译C ++,但似乎使用使用STL很麻烦,主要是由于问题与std :: string 。奇怪的是,炼金术似乎在使用 GNU libstd ++ v3.4.6 。很难相信在GNU的STL中std :: string被破坏了。



有没有人想出了这个问题的解决方法?没有STL的C ++就像一条没有水的鱼。解决方案

这个问题不在STL中。使用线程安全函数 __ gnu_cxx :: __ exchange_and_add 来引用计数 std :: string code> __ gnu_cxx :: __ atomic_add 。问题在于 __ exchange_and_add / __ atomic_add 被打破。

解决方法是重新生成这些函数的良好实现STL。

幸运的是,炼金术发行版为我们留下了一些面包屑。 $ b

 用于构建avm2-libstdc ++。l.bc的源代码可以在这里下载:
http://download.macromedia.com/pub/labs/alchemy/alchemy_gnucpp3-4library_121008.zip

构建avm2-libstdc ++。l.bc:
cd $ ALCHEMY_HOME / avm2-libc
unzip alchemy_gnucpp3-4library_121008.zip
mv lib / avm2-libstdc ++。l.bc lib / avm2-libstdc ++。l.bc.OLD
make

在使用这些库构建make之前,您不应该运行achacks。
提供的Makefiles已经预先配置为在需要的地方直接使用LLVM。

正常情况下,我期望在libstd ++中找到__exchange_and_add / __ atomic_add的实现( $ ALCHEMY_HOME / avm2-libc / lib / avm2-libstdc ++。l.bc ),但由于某些原因,它们在libc中定义( $ ALCHEMY_HOME / avm2-libc / lib / avm2-libc.l.bc )。



我不确定为什么会这样,但是我们可以解决它通过黑客atomicity.h,原型保存的地方。请注意,在解包alchemy_gnucpp3-4library_121008.zip之后,您需要编辑两个 atomicity.h文件:


  • $ ALCHEMY_HOME / avm2-libc / include / c ++ / 3.4 / bits / atomicity.h

  • $ ALCHEMY_HOME / avm2-libc / libstdc ++ / include / bits / atomicity.h



  • 以下是代码:

      / * 
    * __exchange_and_add和__atomic_add在Alchemy的libc中被破坏。
    *将它们替换为功能实现。这不是
    *跨平台,但是这个代码只是为Alchemy编译。 (x),(y))
    #define __atomic_add(x,y)__exchange_and_add_fix((x),(y))
    * /
    #define __exchange_and_add(x,y)__exchange_and_add_fix

    / *
    *正确执行__exchange_and_add。这不是线程安全的,
    *但炼金术不是线程的,所以我们应该没问题。
    * /
    inline _Atomic_word __exchange_and_add_fix(volatile _Atomic_word * __mem,int __val){
    int orig = * __ mem;
    (* __ mem)+ = __val;
    返回orig;





    $ b

    这里有一些测试代码可以运行,以确保重建的STL工作: / p>

      #include< cstdio> 
    #include< string>
    #include< map>
    #include< fstream>
    使用namespace std;

    void string_test(){
    string s1;
    string s2;

    s1 =a;
    s2 = s1; //复制构造函数
    s1 =b;

    //在这里使用你最喜欢的TRACE函数
    printf(s1 =%s \\\
    ,s1.c_str()); // expected:b,actual:b
    printf(s2 =%s \\\
    ,s2.c_str()); // expected:a,actual:b,ERROR
    }

    map_test(){
    map< string,int> test_map;

    test_map [test1] = 1;
    test_map [test2] = 2;
    test_map [test3] = 3;

    string tmp =test1;
    printf(%s:%d \\\
    ,tmp.c_str(),test_map [tmp]);

    $ b $ void ifstream_test()
    {
    std :: ifstream in(test.txt);

    //错误1:
    //尝试查找文件会抛出错误:
    //错误#1006:值不是函数。
    //在:basic_filebuf :: char_traits :: seekoff
    in.seekg(0,std :: ios :: end);
    int length = in.tellg();
    in.seekg(0,std :: ios :: beg);
    printf(文件长度:%d \\\
    ,长度); $(b
    $ b while(in.good()){
    char buffer [512];

    //错误2:
    // RangeError:错误#1125:索引1092156超出范围721.
    //在basic_filebuf :: char_traits :: underflow :: work()
    in.getline(buffer,512,'\\\
    ');

    printf(buffer =%s \\\
    ,buffer);



    int main(){
    string_test();
    map_test();
    ifstream_test();

    返回0;





    $ b请注意,重建后的STL似乎可以解决一些相关的问题:映射 ifstream


    While Alchemy supports compiling C++, it seems that using the using the STL is trouble, mostly due to a problem with std::string. What's strange is that Alchemy seems to be using GNU libstd++ v3.4.6. It's hard to believe that std::string is broken in GNU's STL.

    Has anyone figured out any workarounds for this problem? C++ without the STL is like a fish without water.

    解决方案

    The problem isn't in the STL as such. The GNU implementation of std::string is reference-counted using the thread-safe functions __gnu_cxx::__exchange_and_add and __gnu_cxx::__atomic_add. The problem is that __exchange_and_add/__atomic_add are broken.

    The solution is to rebuild the STL with good implementations of these functions.

    Fortunately, the Alchemy distro leaves some breadcrumbs for us. See $ALCHEMY_HOME/avm2-libc/README, which tells us how to do it:

    The sources used to build avm2-libstdc++.l.bc can be downloaded here:
      http://download.macromedia.com/pub/labs/alchemy/alchemy_gnucpp3-4library_121008.zip
    
    To build avm2-libstdc++.l.bc:
     cd $ALCHEMY_HOME/avm2-libc
     unzip alchemy_gnucpp3-4library_121008.zip
     mv lib/avm2-libstdc++.l.bc lib/avm2-libstdc++.l.bc.OLD
     make 
    
    You should *not* run achacks prior to using these building this library with make.
    The Makefiles provided have been preconfigured to use LLVM directly where needed.
    

    Normally I'd expect to find the implementations of __exchange_and_add/__atomic_add in libstd++ ($ALCHEMY_HOME/avm2-libc/lib/avm2-libstdc++.l.bc), but for some reason they're defined in libc ($ALCHEMY_HOME/avm2-libc/lib/avm2-libc.l.bc).

    I'm not sure why this is the case, but we can work around it by hacking atomicity.h, where the prototypes are kept. Note that after unpacking alchemy_gnucpp3-4library_121008.zip, you'll need to edit two atomicity.h files:

    • $ALCHEMY_HOME/avm2-libc/include/c++/3.4/bits/atomicity.h
    • $ALCHEMY_HOME/avm2-libc/libstdc++/include/bits/atomicity.h

    Here is the code:

      /*
       * __exchange_and_add and __atomic_add are broken in Alchemy's libc.
       * Replace them with functioning implementations.  This isn't
       * cross-platform, but this codebase is only compiling for Alchemy anyway.
       */
      #define __exchange_and_add(x,y) __exchange_and_add_fix((x),(y))
      #define __atomic_add(x,y) __exchange_and_add_fix((x),(y))
    
      /*
       * Correctly implement __exchange_and_add.  It's not thread-safe,
       * but Alchemy isn't threaded, so we should be ok.
       */
      inline _Atomic_word __exchange_and_add_fix(volatile _Atomic_word* __mem, int __val) {
         int orig= *__mem;
         (*__mem)+= __val;
         return orig;
      }
    

    Here is some test code to run to make sure the rebuilt STL works:

    #include <cstdio>
    #include <string>
    #include <map>
    #include <fstream>
    using namespace std;
    
    void string_test() {
        string s1;
        string s2;
    
        s1 = "a";
        s2 = s1; // copy constructor
        s1 = "b";
    
        // use your favorite TRACE function here
        printf("s1= %s \n", s1.c_str()); // expected: "b", actual: "b"
        printf("s2= %s \n", s2.c_str()); // expected: "a", actual: "b", ERROR
    }
    
    void map_test() {
        map<string, int> test_map;
    
        test_map["test1"]= 1;    
        test_map["test2"]= 2;
        test_map["test3"]= 3;    
    
        string tmp= "test1";
        printf("%s : %d \n", tmp.c_str(), test_map[tmp]);
    }
    
    void ifstream_test()
    {
        std::ifstream in("test.txt");
    
        // ERROR 1:
        // Trying to seek file throws an error:
        // Error #1006: value is not a function.
        // at: basic_filebuf::char_traits::seekoff
        in.seekg(0, std::ios::end);
        int length = in.tellg();
        in.seekg(0, std::ios::beg);
        printf("File Length: %d \n", length);
    
        while(in.good()) {
            char buffer[512];
    
            // ERROR 2:
            // RangeError: Error #1125: The index 1092156 is out of range 721.
            // at basic_filebuf::char_traits::underflow::work()
            in.getline(buffer, 512, '\n');
    
            printf("buffer= %s \n", buffer);
        }
    }
    
    int main() {
        string_test();
        map_test();
        ifstream_test();
    
        return 0;
    }
    

    Note that the rebuilt STL appears to fix some related issues with map and ifstream.

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

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