Является ли этот код законным / переносимым?Доступ к данным вне структуры - PullRequest
0 голосов
/ 06 марта 2012

На основании комментария и ответа на другой мой вопрос Я вышел с этим кодом. Комментарий был согласно 5.3.4. Новый [expr.new] ему разрешен доступ за пределами структуры, пока она выделена. Однако я не могу найти раздел, который говорит это.

Я придумал этот код. Я хотел знать, является ли это портативным и полностью определенным и законным. Вывод довольно интересный. в gcc это 10,10,12, в то время как Visual Studio 2010 показывает 12,10,12.

Является ли код допустимым в C ++ 11 или C ++ 03? Я полагаю, что код будет выровнен на любой платформе / процессоре со стандартным компилятором.

-edit- В случае, если ваша ленивая flex_struct является частью, которая делает сомнительные вещи.

#include <iostream>
#include <new>
#include <cstring>

using namespace std;

template <typename STRUCT, typename TYPE> class flex_struct {
    flex_struct(){}
public:
    //should be safe to access and check what length the array is
    static STRUCT* head(char*buff) {
        //is this next line wrong?
        //if((alignof(STRUCT)%reinterpret_cast<size_t>(buff))!=0) { throw std::exception(); }
        return reinterpret_cast<STRUCT*>(buff);
    }

    struct struct_with_array : public STRUCT { TYPE buf[1]; };

    TYPE* buff() {
        //if(length==0) { throw std::exception(); }
        auto p = reinterpret_cast<struct_with_array*>(this);
        return p->buf;
    }
};

typedef short testtype;

struct MyVariableLengthStruct : public flex_struct<MyVariableLengthStruct, testtype> {
    int a, b;
    char c;
};

struct MyVariableLengthStruct2 {
    int a, b;
    char c;
    testtype buf[1];
};
struct MyVariableLengthStruct3a {
    int a, b;
    char c;
};
struct MyVariableLengthStruct3 : MyVariableLengthStruct3a {
    testtype buf[1];
};
int main() {

    auto srcarray=new char[1024];
    //we don't actually need this line which is incorrect anyways (sizeof isnt 1024)
    //memset(srcarray, 0, sizeof(srcarray)); //whats a C++ way to do this w/o writing a loop or function?
    auto v = MyVariableLengthStruct::head(srcarray);
    auto buff = v->buff();
    auto dif1 = (int)buff-(int)v;
    printf("%X %X %d\n", v, buff, dif1);
    MyVariableLengthStruct2 v2;
    auto dif2 = (int)v2.buf-(int)&v2;
    printf("%X %X %d\n", &v2, v2.buf, dif2);
    MyVariableLengthStruct3 v3;
    auto dif3 = (int)v3.buf-(int)&v3;
    printf("%X %X %d\n", &v3, v3.buf, dif3);
}

1 Ответ

4 голосов
/ 06 марта 2012

Я вижу много проблем с этим кодом.

    //is this next line wrong?
    //if((alignof(STRUCT)%reinterpret_cast<size_t>(buff))!=0) { throw std::exception(); }
    return reinterpret_cast<STRUCT*>(buff);

Память, возвращаемая из new char[n], правильно выровнена для объектов запрошенного размера или меньше. Однако статические и автоматические char массивы не являются. Так что, если вы всегда передаете что-то, выделенное new char[n], проблем нет. Если вы передадите указатель на статический или автоматический массив, то выравнивание действительно является проблемой.

struct struct_with_array : public STRUCT { TYPE buf[1]; };

Индексирование вне границ массива - неопределенное поведение. Существует только один элемент buf, к которому вы можете получить доступ. Обратите внимание, что эта проблема не возникает в коде в исходном ответе.

auto p = reinterpret_cast<struct_with_array*>(this);

Я не совсем уверен в действительности этого броска, но подозреваю, что он нарушает строгий псевдоним.

auto srcarray=new char[1024];
memset(srcarray, 0, sizeof(srcarray)); //whats a C++ way to do this w/o writing a loop or function?

Путь C ++ был бы std::vector<char>(1024);, наверное. В любом случае sizeof(srcarray), вероятно, не 1024, а, вероятно, 4 или 8 (равно sizeof(char*)).

auto v = MyVariableLengthStruct::head(srcarray);

Никогда не было построено MyVariableLengthStruct в памяти, указанной srcarray, так что это будет работать только для типов POD.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...