包装结构导致返回本地?

时间:2016-03-17 09:31:13

标签: c++ gcc

我有以下代码,我很难理解为什么打包结构会导致警告(然后在运行时出现段错误。)首先是代码:

#include <iostream>

using namespace std;

template <typename T, std::size_t D, std::size_t S>
struct __attribute__((packed)) C {
  union __attribute__((packed)) ValueType {
    char fill[S];
    T value;
  };

  ValueType data_;

  const T& get() const {
    return data_.value;
  }

  friend
  std::ostream& operator<<(std::ostream& str, const C& f) {
    return str << f.data_.value;
  }     
};

template <typename T, std::size_t D>
struct __attribute__((packed)) C<T, D, D> {
  T value;

  const T& get() const {
    return value;
  }

  friend
  std::ostream& operator<<(std::ostream& str, const C& f) {
    return str << f.value;
  }    
};

template <typename T, std::size_t S = 0>
struct __attribute__((packed)) D {
  C<T, sizeof(T), S> c;
  const T& get() const {
    return c.get();
  }

  friend
  std::ostream& operator<<(std::ostream& str, const D& f) {
    return str << f.get();
  }
};

template <typename T>
struct __attribute__((packed)) D<T, 0> {
  T v;
  const T& get() const {
    return v;
  }

  friend
  std::ostream& operator<<(std::ostream& str, const D& f) {
    return str << f.get();
  }
};

int main(void) {
    D<int64_t> d1;
    cout << d1 << endl;
    D<int64_t, 8> d2;
    cout << d2 << endl;    
}

使用打包(它是GCC特定的)我得到以下内容(gcc 5.2.1 / 5.3.1,c ++ 14-Wall):

packed.cpp: In instantiation of ‘const T& D<T, 0ul>::get() const [with T = long int]’:
packed.cpp:58:16:   required from ‘std::ostream& operator<<(std::ostream&, const D<long int>&)’
packed.cpp:64:13:   required from here
packed.cpp:53:12: warning: returning reference to temporary [-Wreturn-local-addr]
     return v;
            ^
packed.cpp: In instantiation of ‘const T& C<T, D, D>::get() const [with T = long int; long unsigned int D = 8ul]’:
packed.cpp:40:18:   required from ‘const T& D<T, S>::get() const [with T = long int; long unsigned int S = 8ul]’
packed.cpp:45:16:   required from ‘std::ostream& operator<<(std::ostream&, const D<long int, 8ul>&)’
packed.cpp:66:13:   required from here
packed.cpp:27:12: warning: returning reference to temporary [-Wreturn-local-addr]
     return value;

如果结构没有打包 - 代码正常编译然后运行正常(打印垃圾值 - 但这是预期的。)

所以我的问题是 - 为什么打包导致临时的回归?

2 个答案:

答案 0 :(得分:1)

你好Nim我发现这个问题可能是gcc编译器的BUG,你可以在这里看到引用enter link description here

答案 1 :(得分:1)

您正在寻找的是pragma pack。它与您想要的效果相同,但更常见且cross-compiler

注意:使用pragma pack

添加代码的修改版本
#include <iostream>

using namespace std;

#pragma pack(1)    
template <typename T, std::size_t D, std::size_t S>
struct C {
  union ValueType {     
    char fill[S];
    T value;
  };

  ValueType data_;

  const T& get() const {
    return data_.value;
  }   
};
#pragma pack()       

template <typename T, std::size_t D>
struct C<T, D, D> {
  T value;

  const T& get() const {
    return value;
  } 
};

template <typename T, std::size_t D>
struct C<T, D, 0> {
  T value;

  const T& get() const {
    return value;
  } 
};

template <typename T, std::size_t S = 0>
struct D : C<T, sizeof(T), S> {
  friend
  std::ostream& operator<<(std::ostream& str, const D& f) {
    return str << f.get();
  }
};

#pragma pack(1)    
struct E {
    D<int16_t> a;
    D<int64_t, 9> b;
};
#pragma pack()    

int main(void) {
    D<int16_t> d1;
    cout << d1.get() << ' ' << sizeof(d1) << endl;
    D<int64_t, 9> d2;
    cout << d2.get() << ' ' << sizeof(d2) << endl;  
    cout << sizeof(E) << endl;
}