当我偶然发现一个奇怪的问题时,我正在从事一个个人项目。
在一个非常紧密的循环中,我有一个整数,其值在0到15之间。对于值0、1、8和9,我需要得到-1,对于值4、5、12和13,我需要得到1。
我转向godbolt检查一些选项,并惊讶于编译器似乎无法以与if链相同的方式优化switch语句。
链接在这里:https : //godbolt.org/z/WYVBFl
代码是:
const int lookup[16] = {-1, -1, 0, 0, 1, 1, 0, 0, -1, -1, 0, 0, 1, 1, 0, 0};
int a(int num) {
return lookup[num & 0xF];
}
int b(int num) {
num &= 0xF;
if (num == 0 || num == 1 || num == 8 || num == 9)
return -1;
if (num == 4 || num == 5 || num == 12 || num == 13)
return 1; …Run Code Online (Sandbox Code Playgroud) 我使用make的shell命令来填充一些变量,并在输出时指示它们被设置为我期望的值.然而,当我把它们传递给我的制作食谱时,它们都显示为空.我怀疑make正在对结果做一些奇怪的解析.例如:
MyTarget: $(MySources)
LINE='$(shell cat $< | grep GIMME_THE_LINE_I_WANT)'
CH9=$(shell echo $(LINE) | cut -b9)
echo $(CH9) # doesn't print anything
Run Code Online (Sandbox Code Playgroud)
我通过设置手动检查了我的生成器命令SHELL=sh -XV,当我运行相同的命令时,我得到正确的值,它看起来像bash是'归零'我的变量.知道什么是错的吗?
我有数百个代表纸牌游戏纸牌的 pdf 文件。它们是使用 LaTeX 构建的标准 2.5"x3.5" 文件。为了打印它们,我想将它们连接成一个 pdf,每页有 9 张卡片(最多可以容纳)。目前我这样做使用montage -density 300 -tile 3x3 -geometry 750x1050+50+25 a.pdf b.pdf ...
不幸的是,此解决方案存在一些问题:
细节丢失——该-density选项对于获得不错的质量是必要的,结果取决于所需的质量。我的打印机可以 600dpi 打印,所以我应该使用-density 600,但有些打印机无法正确处理。
慢——我不使用 600 的另一个原因是,即使在 300 时,imagemagick 也非常慢,因为我认为它将 pdf 转换为图像,然后将它们连接成 pdf。
有限——此外,当输入文件的数量足够大时,蒙太奇将崩溃而无法创建生成的 pdf。
福利损失——最后,生成的 pdf 不保留原件的元数据。最重要的是,文本不再可选。这意味着我无法在 pdf 中搜索特定卡。
为了解决这个问题,我目前正在使用 pdfunite 制作每页 1 张卡片的长 pdf,然后告诉我的打印机在每页上打印 9 张。结果与预期的效果相当接近,但卡片的大小略有扭曲,这有点问题。
有没有办法在具有特定大小的网格中连接 pdf?
我有一个实现许多功能的标记类型。在一种情况下,我需要这些功能之一来进入无限循环。不幸的是,据我所知,我没有办法对其进行编译,从而不会发出警告。我希望仍然使用-gnatwe以确保我的代码中没有警告,但是如何实现这种功能。
该函数如下所示:
function Foo (This : Some_Type) return Some_Type'Class is
begin
loop
Do_Useful_Stuff_Indefinitely_With (This);
end loop;
-- return This; (if needed?)
end Foo;
Run Code Online (Sandbox Code Playgroud)
我试过了,pragma (No_Return)但那仅适用于过程(并且该Foo函数在其他地方用作适当的函数,因此必须具有相同的签名)。
我也尝试过,pragma Suppress (All_Checks)但是仍然对代码无法到达或缺少返回语句错误提出警告。
有什么办法可以使一次性功能永久运行而不会发出警告?
我似乎无法让GNATCOLL在基于Alpine Linux的Docker容器中进行编译。
到目前为止,我的容器是:
FROM alpine:edge
# Add extra repositories
RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories; \
echo 'http://dl-cdn.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories; \
echo 'http://dl-cdn.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories;
RUN apk add --no-cache build-base coreutils curl-dev gcc-gnat git gmp-dev openssl
# Bootstrap GPRBuild
RUN git clone https://github.com/AdaCore/xmlada.git; \
git clone https://github.com/AdaCore/gprbuild.git; \
cd gprbuild; ./bootstrap.sh --with-xmlada=../xmlada; \
cd ..; \
rm -rf xmlada gprbuild
Run Code Online (Sandbox Code Playgroud)
这工作正常,并为我提供了一个基于GNAT GPR的Ada开发环境的容器。当我尝试在此容器中安装GNATCOLL时,就会出现问题。
运行docker run -i -t <built_image>以下操作:
/ # git clone https://github.com/AdaCore/gnatcoll-core.git
<Typical git clone output>
/ # cd …Run Code Online (Sandbox Code Playgroud) 我有一个不寻常的情况,根本没有执行精简代码.这不是详细说明问题,而是所有问题的详细阐述.
问题在于我没有"讨论"有关的单位,但理论上它仍然应该是可访问的,只要它的详细说明发生.
当然,我可以为相关单元添加一个无用的"with",但在我的实际用例中,我必须使用大量单元.
我的问题是,如果在代码中,通过编译指示,在gpr项目文件中,或通过命令行开关,我可以强制编译器包含文件,即使它认为文件未被引用?
这是一个最小的工作示例:
as.ads:
package As is
type A is tagged null record;
type Nothing is null record;
function Create (Ignored : not null access Nothing) return A;
function Image (From : A) return String;
end As;
Run Code Online (Sandbox Code Playgroud)
as.adb:
package body As is
function Create (Ignored : not null access Nothing) return A is
(null record);
function Image (From : A) return String is ("A");
end As;
Run Code Online (Sandbox Code Playgroud)
finder.ads:
with Ada.Tags;
package Finder is
procedure Register (Name : String; Tag …Run Code Online (Sandbox Code Playgroud) 我正在研究Ada中的一个项目,并且想要一个自定义的makefile(因为我打算最终与c和python接口,并且我非常熟悉makefile语法,而且根本不熟悉gnatmake项目语法).我搞乱了自定义编译,并认为我有它工作,但我的makefile至少看起来它完全相同的命令行执行在绑定阶段遇到问题.
我想我可能有一个off-by-one目录错误,或者过度/不完全复杂的东西.
无论如何,我的项目目前包含3个源目录(但会有更多的目录).Model包含'logic',util包含常用实用程序,test包含未打包的'main'程序.最后我还会在我的src目录中找到一些"主要"程序.ASCII图片:
project
\- bin
\- test
\- ....out
\- other_dirs_coming_soon
\- ....out
\- ....out
\- obj
\- all the mess that ada compilation makes
\- including .o, .ali, and b~whatever.ad(b/s)
\- src
\- model
\- ....ad(b/s)
\- util
\- ....ad(b/s)
\- ...
Run Code Online (Sandbox Code Playgroud)
我尝试了一个非常接近我想要的"基本"makefile:
.PHONY: clean test
MAKE=gnatmake
INCLUDE_DIRS=-Imodel -Iutil -Itest
GNATMAKEFLAGS=-g -fprofile-arcs -ftest-coverage --GNATLINK="gnatlink -v" --GNATBIND="gnatbind -v"
GCCFLAGS=-g -fprofile-arcs -ftest-coverage
OBJDIR=../obj
BINDFLAGS=-a0$(OBJDIR)
PLAYER_TEST_EXE=../bin/player_test.out
test : $(PLAYER_TEST_EXE)
$(PLAYER_TEST_EXE) : test/player_test.adb
gnatmake $< -D $(OBJDIR) $(INCLUDE_DIRS) -o $@ $(GNATMAKEFLAGS)
clean …Run Code Online (Sandbox Code Playgroud) 我有一个基于 GPR 的大型项目,编译可能需要 30 多分钟。
在分析了构建过程后,我注意到许多明显的低效率(多次调用 gprbuild 而不是聚合、过度使用替代文件而不是配置等)。我想知道是否有一些方法可以“分析”构建过程以查看需要这么长时间。
特别是即使是单个文件发生变化并且出现错误时,重新编译也需要大约5分钟。从理论上讲,应该很快意识到必须重新编译该文件(这是唯一一个这样做的)并开始编译过程,迅速发现错误。
从详细的输出来看,解析用于定义构建的大量 gpr 文件网络似乎需要相当长的时间,但我想知道它大部分时间都花在了哪里。
因此我的问题是:是否可以分析由 gprbuild 完成的构建?如果是这样,如何?
我正在尝试编写一个复制函数的函数(并最终修改其程序集)并返回它.这适用于一个级别的间接,但在两个我得到段错误.
这是一个最小(非)工作示例:
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#define BODY_SIZE 100
int f(void) { return 42; }
int (*G(void))(void) { return f; }
int (*(*H(void))(void))(void) { return G; }
int (*g(void))(void) {
void *r = mmap(0, BODY_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
memcpy(r, f, BODY_SIZE);
return r;
}
int (*(*h(void))(void))(void) {
void *r = mmap(0, BODY_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
memcpy(r, g, BODY_SIZE);
return r;
}
int main() {
printf("%d\n", f());
printf("%d\n", G()());
printf("%d\n", g()());
printf("%d\n", H()()());
printf("%d\n", h()()()); // This …Run Code Online (Sandbox Code Playgroud) 我不确定这是我的gcc(4.8.5)或gprbuild(2.2.0)版本中的错误,但是当我尝试编译项目时,有一个特定的函数,其主体导致编译器崩溃STORAGE_ERROR.当我构建时,-cargs -v我看到这gnatl -quiet ...是崩溃前最近输出的命令.
所讨论的函数从属于特定类型层次结构的标签产生信息性字符串.它看起来像:
function Tag_To_String (From : Ada.Tags.Tag) return String is (
if From = A'Tag then "This is tag A"
elsif From = B'Tag then "This is tag B"
-- ...
elsif From = Z'Tag then "This is tag Z"
else "");
Run Code Online (Sandbox Code Playgroud)
如果我将该主体更改为:我可以成功编译它:
function Tag_To_String (From : Ada.Tags.Tag) return String is ("");
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
gcc -c -gnat12 sourcefile.adb
raised STORAGE_ERROR : stack overflow or erroneous memory access
gprbuild: *** compilation phase failed …Run Code Online (Sandbox Code Playgroud)