zoukankan      html  css  js  c++  java
  • c++中动态尾随内存的技巧和定位new

    c 和 c++ 最大的特点就是对内存的自由操作,数据类型,其实都是对内存的一种解释方式。C语言中常用的一个技巧就是尾随数据,网络编程中经常会用到这个特性,

    特别是以前写完成端口的时候,这个特性肯定是会用到,跟IOCP的API特性相关。c++中也有类似的new也可以使用。

    e1:尾随内存与指针解释

    // c++ std 
    #include <iostream>
    
    // c std
    #include <cstdlib>
    #include <cstring>
    
    
    struct TestData {
        int data_size_;
        char data_[0];
    };
    
    void foo1() {
        std::cout << "sizeof(TestData) = " << sizeof(TestData)<<std::endl;
        int len = sizeof(TestData) + 100*sizeof(int);
        char *buffer = "hello world";
        TestData * data_ptr = reinterpret_cast<TestData*>(new char[len]);
        if (nullptr != data_ptr) {
            data_ptr->data_size_ = 100;
            memcpy(data_ptr->data_, buffer, strlen(buffer) + 1);
            std::cout << data_ptr->data_ << std::endl;
            std::cout << reinterpret_cast<char *>(data_ptr+1) << std::endl;
            std::cout << "sizeof(TestData) = " << sizeof(TestData)<<std::endl;
        }
        
    }
    int main(int argc, char* argv[]){
        foo1();
        getchar();
        return 0;
    }

    输出结果:

    sizeof(TestData) = 4

    hello world

    hello world

    说面:动态分配的内存比TestData本身的数据大小4要大,而TestData的成员data_是不计内存的,只是其地址依然是在data_size_的内存地址之后。给data_的赋值其实利用的是其后的数据内存,而不是TestData本身的内存,不过,实际使用时最好还是将data_声明为char data_[1]。

    e2:C++中的定位new

    通常我们用new来动态分配一个对象或者一个对象数组,上面的代码中分配内存时,分配了相对足够大的内存,然后在其上面构建字符串。new操作符其实也可以在已有内存上构建对象,继续在刚才的代码上改进一下。

    void foo2() {
        char * buffer = new char [500];
    // 利用new在已有内存上构建对象 TestData
    *data1 = new (buffer) TestData; if (nullptr == data1) { return; }
    // 再次利用new在data1后构建第二个TestData对象
    // 此时new是没有分配内存的 TestData
    *data2 = new (data1 + 1) TestData; if (nullptr == data2){ return; } data1->data_size_ = 4; memcpy(data1->data_, &data1->data_size_, sizeof(data1->data_size_)); // 这个时候, 由于data2的内存仅随data1之后,data2->data_size_的值为4 std::cout << "data1:" << data1 << std::endl; std::cout << "data2:" << data2 << std::endl; std::cout << "data2->data_size_:" << data2->data_size_ << std::endl; } int main(int argc, char* argv[]){ foo2(); getchar(); return 0; }

    输出结果:

    data1:001EFBE0

    data2:001EFBE4

    data2->data_size_:4

  • 相关阅读:
    LNMP分离部署
    PXE
    Mysql
    07.23 课堂随笔 学习了相关的标签
    [Prodinner项目]学习分享_第三部分_Service层(业务逻辑层)
    Beginning Windows Azure Development Guide
    5分钟浅析简单工厂模式
    [Prodinner项目]学习分享_第一部分_Model层
    [Prodinner项目]学习分享_第四部分(完结篇)_Controller层(控制器)
    C# Windows service 开发笔录
  • 原文地址:https://www.cnblogs.com/knight-monkey/p/Monkey-Knight_201604031134.html
Copyright © 2011-2022 走看看