вторник, мая 22, 2007

Полезный ключ компилятора MS VC++

Я уже довольно давно читаю блог команды разработчиков Visual C++ и должен сказать что это довольно таки занудный блог. Но вот последняя статья в нем - буквально таки жемчужина.

Не очень часто мы сталкиваемся с проблемой неодинакового выравнивания одних и тех же классов в разных единицах трансляции. Проблему трудно диагностировать и даже очень трудно. Так вот статья рассказывает про замечательный и конечно же НЕ документированный и не поддерживаемый ключ компилятора:

/d1reportSingleClassLayoutXXX, где XXX - интересующее нас имя класса.

При компиляции с этим ключом, компилятор показывает, как с его точки зрения "разложился" класс XXX. Вот код из статьи:

// a.h – share class definition (code has been corrected from original post)

#pragma once

class Test_A {
public
:

Test_A(){ c = 'X'; data = 0; }

~Test_A(){ if(data) delete [] data; }

char c;
char* data;

};

void Test_A_Loader(Test_A&);

// loader.cpp - loader defn.
#include
//for strcpy
#include
"a.h"

void Test_A_Loader(Test_A& a) {

a.c = 'p';
a.data = new char[10];
strcpy(a.data, "3.14159");

}

// main.cpp - main program
#include
// for printf

#include "a.h"

int main(){

Test_A a;
Test_A_Loader(a);
printf("%c : %c %c %c %c\n", a.c, a.data[0], a.data[1], a.data[2], a.data[3]);

}

Данный код компилируется вот так (для того чтобы воспроизвести ошибку):

cl main.cpp /Zp2 /c
cl loader.cpp /Zp1 /c
link main.obj loader.obj


При этом конечно возникает ошибка с выравниванием, поскольку класс Test_A выровнен по разному в единице трансляции main.cpp и в единице трансляции loader.cpp.

А вот вывод компилятор при использовании волшебного ключика '/d1reportSingleClassLayoutTest_A' (почему то в статье вывод компилятора целиком не приведён, а мне кажется что это интересно):

1>------ Build started: Project: ClassLayout, Configuration: Debug Win32 ------
1>Compiling...
1>stdafx.cpp
1>Compiling...
1>loader.cpp
1>class Test_A size(5):
1> +---
1> 0 | c
1> 1 | data
1> +---
1>class Test_A size(5):
1> +---
1> 0 | c
1> 1 | data
1> +---
1>Compiling...
1>ClassLayout.cpp
1>class Test_A size(6):
1> +---
1> 0 | c
1> | <alignment member> (size=1)
1> 2 | data
1> +---
1>class Test_A size(6):
1> +---
1> 0 | c
1> | <alignment member> (size=1)
1> 2 | data
1> +---
1>Linking...
1>Embedding manifest...
1>Build log was saved at "file://l:\ClassLayout\Debug\BuildLog.htm"
1>ClassLayout - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Вот такой вот замечательный ключик. А я уж от их блога отписываться хотел.


Комментариев нет: