标签: c++builder-xe4

在现代C++ Builder应用程序中使用预编译头文件的最佳实践是什么?

我目前正在将一个大型RAD Studio 2010项目迁移到XE4.作为其中的一部分,我正在重新创建许多项目文件.我想借此机会确保我们使用最佳的预编译头文件机制,因为似乎有几种方法可以做到这一点.

现在我们只编译32位,但将来会使用64位编译器.

以下是我们目前在2010年所做的工作,以及为什么我不确定在XE4中要做什么:

在RAD Studio 2010中

我们有一个文件PchApp.h,其中包含<vcl.h>许多其他常用的头文件,主要是项目中各种常用核心类的头文件.此标头包含在每个CPP文件的顶部,后跟#pragma hdrstop如下所示:

// Top of .cpp file
#include "PchApp.h"
#pragma hdrstop

// Normal includes here
#include "other.h"
#include "other2.h"
// etc
Run Code Online (Sandbox Code Playgroud)

然后,我们在项目选项的预编译标题部分中进行以下设置:

当前RS2010预编译头设置

编译起来并不是特别快(大约350,000行代码需要12分钟.)我不确定:

  • "注入预编译头文件":这应该注入PchApp.h吗?
  • "缓存预编译头文件(必须与-H或-H"一起使用"xxx")": - H选项是"PCH文件名",因此我们正在使用它,但是预编译头的确定点是它"缓存"或每次编译预编译一次.这有什么额外的区别?
  • 我们应该在.cpp文件中包含两行包含PchApp.h和pragma hdrstop吗?有没有办法在项目选项中执行此操作,而不是在每个文件中复制这两行?他们有必要吗?

换句话说,我不确定这些是正确的还是最佳的设置,但是从阅读文档中我同样不确定什么会更好.我知道我不太了解所有选项 - 这个问题的一个原因:)

在RAD Studio XE4中

XE4 32位编译器的选项对话框是相同的,但有两件事让我感到困惑和/或让我不确定当前的2010方法是最好的.

1.默认行为

在创建新的VCL Forms项目时,IDE会创建一个默认名为Project1PCH1.h的标头,该标头旨在作为项目的预编译标头. 此标头包含<vcl.h><tchar.h>,并在项目管理器中显示为节点.它不包含在默认的Form1.cpp中,但#include <vcl.h>后面#pragma hdrstop是Form1.cpp的最顶层,后跟其他标题.

使用此标题的新项目的默认XE4设置对话框是: XE4默认预编译头设置

我(天真地?)正在假设默认值实际上是最佳/最佳设置.有些事情困扰我:

  • Project1PCH1.h在任何地方的预编译头设置中都没有提到项目的假定预编译头.
  • 标头不会被缓存
  • 未指定PCH文件名(这应该是Project1PCH1.h?)
  • .cpp文件也不包括Project1PCH1.h …

c++builder precompiled-headers c++builder-xe4

23
推荐指数
1
解决办法
1451
查看次数

与C++ Builder 2010相比,C++ Builder XE4中EXE大小增加三倍的原因是什么?

我已将项目从RAD Studio 2010升级到RAD Studio XE4.该项目主要是使用C++ Builder的一半RAD Studio进行的C++,其中包括Delphi的一些内容.

在2010年,Release版本为22MB.在XE4下,相同的Release版本为55MB.

这是一个问题,因为:

  • 对于EXE来说,55MB非常大
  • 启动程序需要相当长的时间(不多,但有些.)
  • 我们的许多客户在海上时从偏远地区或船上下载新版本.大小事项.

是什么导致这种情况,我该如何解决?


笔记

  • 奇怪的是,调试版本仍然只有23MB.项目设置似乎非常相似.我扩展了选项集的导出,只看到<UsePackages>True</UsePackages>Release not Debug中存在的东西; 删除它没有任何区别.除此之外,还启用了代码优化,缺少_DEBUG定义.
  • 调试信息用于发布版本生成的,而是进入一个外部.tds文件.(这将在未来用于EurekaLog,目前允许我们调试程序的发布版本.)我想知道链接器是否在调试信息中链接,但据我所知,C++链接器始终将调试信息放入外部文件,存在,加上EurekaLog尚未在构建中启用.
  • 项目文件(.cbproj)是在XE4中创建的,而不是从旧的2010年升级而来.我创建了新项目并添加了旧的.cpp和.pas文件.这是为了避免升级引起的问题 - 在Embarcadero论坛上,经常建议在升级IDE版本时重新创建项目.在此之前,我确实遇到的问题比2010年少.
  • 有很多提及Delphi XE2 + EXE明显比旧版Delphi产生的大.(1,2,3,4,5,6).尽管在C++接头是一种通过用Delphi不同,它是可能的原因是相似的.
    其原因似乎主要是Delphi RTL代码使用的RTTI,在Delphi项目中可以通过指定删除{$WEAKLINKRTTI ON}.该XE4文件没有提到一个相当的C++编译链接.有#pragma explicit_rtti(C++类似物{$RTTI})和__declspec(delphirtti)(C++类似物{$M}/{$TYPEINFO}).
  • 该项目使用运行时包和动态RTL进行链接.它是一个32位VCL表单应用程序.我在Windows 7上安装了XE4 Update 1.
  • 编辑: David Heffernan在下面的评论中询问每个项目的.map文件大小.
    发行版.map大小为17MB,.tds大小为80MB.
    Debug现在已停止链接,链接器报告它内存不足(一个旧的,早就应该修复过的bug了.)没有生成.map或.tds文件,所以我不能给出比较大小准确.从内存来看,.tds大概是100MB,不幸的是我不记得.map的大小了.如果我得到项目链接,我会更新问题.
  • 再次编辑:我找到答案(sortof) - 将'扩展内联函数'关闭会将EXE大小减小到预期值.这令人费解 - 请参阅下面的答案.请注意,调试版本已经关闭并仍然无法链接,从而导致内存不足错误.
    我还没有将我的答案标记为正确,以防万一有人可以提供一些有关正在发生的事情的见解,这将是一个更好的答案,而不仅仅是"关闭此选项".

delphi linker c++builder c++builder-xe4

9
推荐指数
1
解决办法
1352
查看次数

MSBuild在Cpp.Targets中使用新的XE4项目搜索"True.dpr"失败

msbuild在RAD Studio XE4中遇到了一些奇怪的错误,我正在寻求帮助来诊断正在发生的事情.我已经遇到了这个问题已经有几个星期了,但是我自己也没有成功解决这个问题 - 时间问得更广泛了.症状是:

  • 通过在IDE中构建和运行的项目,msbuild Project.cbproj似乎可以正常工作
  • 正常运行msbuild Project.cbproj /t:Clean,并删除中间文件.输出的可视扫描不显示任何异常文件被删除 - 只有.obj文件,链接器状态文件,最终EXE等.
  • 但是在清洁或干净结账后运行msbuild Project.cbproj /t:Build或只是简单失败,并显示以下错误消息:msbuild Project.cbproj

Microsoft(R)Build Engine版本3.5.30729.5420 [Microsoft .NET Framework,版本2.0.50727.5472]版权所有(C)Microsoft Corporation 2007.保留所有权利.

Build build 12/09/2013 10:35:03.节点0上的项目"C:\ projects\Project.cbproj"(默认目标).

_PasDepCheck:已修改:Source\Common\resample.pas _PasCoreCompile:Embarcadero Delphi for Win32编译器版本25.0版权所有(c)1983,2013 Embarcadero Technologies,Inc.C:\ Program Files(x86)\ Embarcadero\RAD Studio\11.0\Bin\CodeGear.Cpp.Targets(191 1,5):错误F1026:找不到文件:'True.dpr'完成构建项目"C:\ projects\Project.cbproj"(默认目标) - 失败.

建立失败.

"C:\ projects\Project.cbproj"(默认目标)(1) - >(_PasCoreCompile目标) - > C:\ Program Files(x86)\ Embarcadero\RAD Studio\11.0\Bin\CodeGear.Cpp.Targets(1 911,5):错误F1026:找不到文件:'True.dpr'

0 Warning(s)
1 Error(s)
Run Code Online (Sandbox Code Playgroud)

有些事情让我觉得这个:

  • 它在顶部列出了两个版本的.Net,在方括号中列出了较旧的版本.它可以加载或使用两个框架的一部分吗?
  • True.dpr不存在,也无法找到手动搜索.cbproj文件True.dprTrue …

msbuild c++builder delphi-xe4 c++builder-xe4

5
推荐指数
2
解决办法
1531
查看次数

boost :: system :: error_code :: message()使用boost :: asio socket抛出访问冲突异常

我正在实现一个客户端应用程序,它必须与硬件设备建立少量套接字连接.我已将问题分解为以下小代码子集

boost::system::error_code ec;
std::string str_message = ec.message();  // no access violation before connect()
std::string str_port = "502";
std::string str_ip = "192.168.12.198";

boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(),str_ip,str_port);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::socket s(io_service);

ec = s.connect(*iterator,ec);
if (ec)
{
    // connection error of some kind.
    std::string str_debug = ec.message();  // BANG!!!!

}
Run Code Online (Sandbox Code Playgroud)

我正在使用Embarcadero RAD studio XE4 C++ Builder,当我在主VCL线程中运行上面的代码时,它运行正常.当我和多个连接运行它,我上面的代码中的多个实例运行TThread类,这是当我进入访问冲突的问题-它似乎是,当error_code被修改的connect电话,该内部构件m_cat中的error_code实例变为NULL,所以当我打电话时,message()我得到访问冲突.即使我只运行一个后台线程,也会发生这种情况.

上面的代码是否有可能在我需要使用它的方式上不是线程安全的?我试图找出为什么这个代码不会在后台线程中运行,但找不到任何关于它的东西.

我运行的升级版本是1.50,因为这是用于在RAD studio中构建64位应用程序的集成版本.

是否有其他人在多线程设置(Embarcadero或其他)中遇到此问题,如果是这样,你是如何解决它的?或者这个类是不安全的以多线程方式使用?

c++ multithreading boost-asio c++builder-xe4

4
推荐指数
2
解决办法
4421
查看次数

无法检测到C++同步boost :: asio :: ip :: tcp :: socket连接被关闭

boost::asio用来与同一台计算机上运行的node.js TCP服务器应用程序建立同步TCP套接字连接.我在Windows上使用Embarcadero RAD studio XE4构建64位应用程序,该应用程序使用Embarcadero集成升级版本1.50.

除了node.js TCP服务器关闭之外,工作正常.发生这种情况时,我从套接字读取时,我的C++客户端应用程序没有检测到断开连接.但是,当我写入套接字时,它确实检测到断开连接.

我目前的代码是在尝试了解增强文档和SO上的各种答案之后编写的.代码的读取部分如下(我省略了检查紧凑性的错误代码)

boost::system::error_code ec;
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket s(io_service);
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"),m_port);

ec = s.connect(ep,ec);
std::size_t bytes_available = s.available(ec);
std::vector<unsigned char> data(bytes_available,0);

size_t read_len = boost::asio::read(s,  boost::asio::buffer(data),boost::asio::transfer_at_least(bytes_available),ec);

if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
{
    // disconnection
    break;
}
Run Code Online (Sandbox Code Playgroud)

这不是一个很好的系统,因为它在循环内部运行自己的线程并不断轮询数据直到程序关闭.通常情况下,read()当没有数据时我不会在套接字上执行,但在这种情况下我会这样做,因为所有文档都让我相信只有在执行读取或写入套接字时才会检测到套接字断开连接.问题是上面的代码在node.js应用程序关闭时根本不会检测到断开连接.如果我正在编写,我会检测到它(代码的写入部分使用与读取相同的boost :: asio :: error`错误),但在读取时却没有.

显然,我无法执行大于可用字节数量的读取,或者我的线程将阻塞,我将无法在我的线程循环中执行写入.

我错过了另一个特定的增强错误代码来检测错误情况吗?或者这是一个特别是零长度读取的问题.如果是这样的话,我还有其他选择吗?

目前我正在让node.js服务器在关闭时关闭我检测到然后自己关闭客户端的时候写入特定的消息.但是,这有点像黑客,如果可能的话,我更愿意采用干净的方法来检测断开连接.

c++ sockets c++builder boost-asio c++builder-xe4

0
推荐指数
1
解决办法
1830
查看次数