我有一个模板类,它有两个静态成员变量,一个int另一个 std::array<volatile uint_fast32_t, 8> .当我用两个不同的类(它们本身就是模板)作为模板参数实例化模板时,对于其中一个实例,一切都完美无缺,即两个变量只有一个拷贝。然而,对于另一个,数组在符号表中重复出现,而且我的代码确实有一个错误,当我在一个编译单元中的数组中设置一个值时,更改不会出现在另一个编译单元中。
这是针对嵌入式系统的,这就是将静态模板用于一种编译时多态性这种奇怪习惯的原因。
在代码中: header 声明类本身
//dacmux.h
namespace HAL {
template<typename dac_write_sequence_t,
unsigned int chans,
typename sample_t = uint_fast32_t>
struct dacmux {
private:
typedef std::array<volatile sample_t, chans> chans_t;
static chans_t channels;
static unsigned int nextchan;
...
};
//The static variables defined here,
//count on the compiler/linker to make sure
//there is exactly one definition
template<typename dac_write_sequence_t,
unsigned int chans,
typename sample_t>
typename dacmux<dac_write_sequence_t, chans, sample_t>::chans_t dacmux<dac_write_sequence_t, chans, sample_t>::channels{0};
template<typename dac_write_sequence_t, unsigned int chans, typename sample_t>
unsigned int dacmux<dac_write_sequence_t, chans, sample_t>::nextchan = 0;
template<typename dac_t, typename addr_t, typename en_t>
struct muxed_setter {
...
};
template<typename dac_t>
struct dac_setter {
...
};
}//namespace HAL
分发硬件定义的 header :
//Hardware_types.h
...
//Multiplexer for the internal DAC
typedef HAL::dacmux<HAL::muxed_setter<dac1, mux1_addr, mux1_en>, 8> mux1;
//Sequencer for writing the external DAC values
typedef HAL::dacmux<HAL::dac_setter<extdac1>, 8> extdac_sequencer;
...
header Hardware_types.h包含在两个源文件中,main.cpp , DebugConsole.cpp , 两者都使用 mux1和 extdac_sequencer .
据我了解,根据this one等回答和许多其他的一样,编译器应该注意每个静态成员变量在模板的每次实例化中都被恰好实例化一次?
但是,当我设置 extdac_sequencer::channels 的值时在 DebugConsole.cpp , 更改不会反射(reflect)在 main.cpp 中声明的中断处理程序中.同样适用于 mux1::channels .实际上,符号表的摘录,由 objdump -t 从 .elf 中提取:
20000280 l O .bss 00000004 _ZN3HAL6dacmuxINS_10dac_setterINS_6ti_dacINS_3SPIINS_5SPI_2EEEN5GPIOs5pin_tINS6_1BELj12EEENS_12_GLOBAL__N_110xx68_frameENSA_12command_xx68ENSA_12channel_xx68EEEEELj8EjE8nextchanE
...
20000254 l O .bss 00000020 _ZN3HAL6dacmuxINS_10dac_setterINS_6ti_dacINS_3SPIINS_5SPI_2EEEN5GPIOs5pin_tINS6_1BELj12EEENS_12_GLOBAL__N_110xx68_frameENSA_12command_xx68ENSA_12channel_xx68EEEEELj8EjE8channelsE
...
20000288 l O .bss 00000020 _ZN3HAL6dacmuxINS_10dac_setterINS_6ti_dacINS_3SPIINS_5SPI_2EEEN5GPIOs5pin_tINS6_1BELj12EEENS_12_GLOBAL__N_110xx68_frameENSA_12command_xx68ENSA_12channel_xx68EEEEELj8EjE8channelsE
...
20000234 w O .bss 00000020 _ZN3HAL6dacmuxINS_12muxed_setterIN4DACs11DAC_channelILj1EN5GPIOs5pin_tINS4_1AELj4EEEEENS4_12bit_stripe_tINS4_1CELj6ELj3EEENS5_ISA_Lj9EEEEELj8EjE8channelsE
...
2000027c w O .bss 00000004 _ZN3HAL6dacmuxINS_12muxed_setterIN4DACs11DAC_channelILj1EN5GPIOs5pin_tINS4_1AELj4EEEEENS4_12bit_stripe_tINS4_1CELj6ELj3EEENS5_ISA_Lj9EEEEELj8EjE8nextchanE
所以 nextchan变量在每个实例化中出现一次,正如它应该的那样,对于 mux1 channels也是如此.但是,对于 extdac_sequencer , channels变量重复,我相信这解释了错误。
我做错了什么,还是编译器或链接器错误?
编译器:GCC arm-none-eabi 5.2.1 20151202
链接器:arm-none-eabi-ld 2.25.90.20151217
链接器选项:-T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"Synth1Firmware.map" -Xlinker --cref --specs=nano.specs
我已经缩小了发生这种情况的条件:
如果dacmux的第一个模板参数本身不是模板,一切正常,即没有重复的符号:
struct extdac1_setter {
template<typename sample_t>
inline static void update(sample_t val, unsigned int addr) {
extdac1::write_and_update(val, addr);
}
};
//Multiplexer for external DAC, works
typedef HAL::dacmux<extdac1_setter, 8> extdac_sequencer;
但是,如果模板参数本身是模板化的,我会遇到重复符号问题:
template<typename dac_t>
struct dac_setter {
template<typename sample_t>
inline static void update(sample_t val, unsigned int addr) {
dac_t::write_and_update(val, addr);
}
};
//Multiplexer for external DAC, this produces a duplicate symbol
typedef HAL::dacmux<dac_setter<extdac1>, 8> extdac_sequencer;
在这里,extdac1 本身也是一个模板:
typedef HAL::DAC8568<dacspi, typename dacspi::nss> extdac1;
...和dacspi是一个模板,等等。此外,在确实有效的情况下,使用另一个实例,而 dac_write_sequence_t是一个模板,它不再是模板的模板。所以我开始认为这是模板递归深度的问题,即 ld看起来不够深入。
另一个有趣的观察:在与具有重复符号完全相同的情况下,Eclipse 语法突出显示在声明 extdac_sequencer 的行上显示“无效的模板参数” ,尽管实际的编译步骤已经完成。
最佳答案
事实证明这是我的愚蠢行为:我在定义模板 HAL::DAC8568 的 header 中使用了一个未命名的命名空间,它被定义为
template<typename spi_t, typename nss_t> using DAC8568 = ti_dac<spi_t, nss_t,
xx68_frame,
command_xx68,
channel_xx68>;
这里的xx68_frame、command_xx68和channel_xx68都是在未命名的命名空间中定义的(这当然是错误的做法 header )。这当然意味着当从不同的编译单元实例化时,我为它们每个得到一个不同的类型,因此为 DAC8568 等得到一个不同的类型,所以它是完美的很自然地得到静态变量的另一个实例。
将未命名的命名空间更改为 namespace detail 可立即解决问题。
我仍然对链接器输出中损坏的名称看起来完全相同这一事实感到有些困惑。怎么可能?
无论如何,我们从中了解到以下内容(其中一些我们已经知道):
关于C++类成员的静态成员变量被实例化两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37510480/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。
我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.