草庐IT

c++ - STL 实现之间分配策略的差异?

coder 2024-02-22 原文

我刚刚发现 basic_string<char> 的默认分配器GCC 4.9(使用 MinGW-w64)实现中的 STL 不使用全局 operator new()但也许直接malloc ,但 MSVC 11 (VS 2012) 中的实现使用它。

还在 CentOS 下尝试了 gcc 4.4.6,并按预期调用了运算符。

为什么会有这样的差异,MSVC 方法不是正确的方法吗?我希望能够通过提供我自己的 operator new() 来跟踪 STL 完成的每个分配。 .

这是我的测试代码:

#include <limits>
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <memory>
#include <map>
using namespace std;

template<typename T>
struct MallocAllocator
{
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    pointer allocate(size_type n, const void* = 0) {
        cout << "Custom: " << sizeof(value_type) * n << endl;
        return static_cast<pointer>(malloc(sizeof(value_type) * n));
    }

    void deallocate(pointer ptr, size_type) {
        free(ptr);
    }

    // boilerplate follows
    MallocAllocator() {}

    MallocAllocator(const MallocAllocator&) {}

    size_type max_size () const throw() { return std::numeric_limits<std::size_t>::max() / sizeof(T); }

    template <typename Other>
    MallocAllocator(const MallocAllocator<Other>&) {}

    MallocAllocator& operator=(const MallocAllocator&) { return *this; }

    template <class Other>
    MallocAllocator& operator=(const MallocAllocator<Other>&) { return *this; }

    template <typename Other>
    struct rebind { typedef MallocAllocator<Other> other; };

    pointer address(reference ref) const {
        return &ref;
    }

    const_pointer address(const_reference ref) const {
        return &ref;
    }

    void construct(pointer ptr, const value_type& val) {
        ::new(ptr) value_type(val);
    }

    void destroy(pointer ptr) {
        ptr->~value_type();
    }
};

template <typename T, typename U>
inline bool operator==(const MallocAllocator<T>&, const MallocAllocator<U>&) {
    return true;
}

template <typename T, typename U>
inline bool operator!=(const MallocAllocator<T>& a, const MallocAllocator<U>& b) {
    return !(a == b);
}

void *operator new(size_t s) {
    cout << "Global: " << s << endl;
    return (void*)malloc(s);
}

void *operator new[](size_t s) {
    cout << "Global: " << s << endl;
    return (void*)malloc(s);
}

int main(int argc, char** argv) {
    //basic_string<char, char_traits<char>, MallocAllocator<char> > s;
    basic_string<char> s;
    s = "dfasdf";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += ".";
    s += "dfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfsdfasdfsdfasfs";

    cout << s << endl;

#ifdef _MSC_VER
    system("pause");
#endif

    return 0;
}

使用 MinGW-w64 的 GCC:当我使用自定义分配器时,我看到了分配。当我不使用它时,我什么也看不到。

最佳答案

我认为这可能只是 mingw-w64 运行时或“mingw-builds”中的错误...

“mingw-builds”构建中使用的运行时可能已经从预构建的 dll 中导出了使用 std::string 和默认分配器(我没有能够确认这一点,它可能是 mingw-w64 运行时本身),MSVC 过去做了类似的事情(虽然我不知道这是否导致了类似的错误)。

我尝试过的一些组合:

  • 使用 vector 和覆盖的 operator new 构建的“mingw-builds”按预期使用。
  • 使用到运行时的静态绑定(bind) (--static) 构建可执行文件 (mingw-builds) 按预期工作(对于 stringvector).
  • “nuwen”的构建和对 stringvector 的预期工作。
  • VS2013 还调用覆盖的 operator newstd::allocator 一起使用(有和没有 /MD 选项)。
  • VS2008(使用 /MD)产生了意外的输出(std::string 是从运行时 dll、IIRC 导出的)。

据我所知,std::string 是从“libstdc++-6.dll”导出的,因此与 ::operator new 等的绑定(bind)是可能已经在二进制文件中为 string 分配修复了(如您所知)。

对分配器的简单更改;

template <class C>
struct myallocator : std::allocator<C> {
};

允许重写的全局 operator new 按预期与“mingw-builds”一起工作。您已经通过完整的自定义分配器注意到这一点,但此处的简单推导支持“默认”字符串类可能源自 dll 的概念。

#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <vector>
// replacement of a minimal set of functions:
void* operator new(std::size_t sz) {
    std::printf("global op new called, size = %d\n",sz);
    return std::malloc(sz);
}
void operator delete(void* ptr) noexcept
{
    std::puts("global op delete called");
    std::free(ptr);
}
template <class C>
struct myallocator : std::allocator<C> {
};
int main() {
     using namespace std;

     vector<int> def;
     def.resize(100000);

     basic_string<char, char_traits<char>, myallocator<char>> abc;
     abc.resize(100000);
}

命令行

cl /EHsc file.cpp
cl /EHsc /MD file.cpp
g++ --std=c++11 file.cpp
g++ --static --std=c++11 file.cpp

关于c++ - STL 实现之间分配策略的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25680528/

有关c++ - STL 实现之间分配策略的差异?的更多相关文章

  1. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  2. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  7. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  8. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  9. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  10. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

随机推荐