小编Lam*_*eta的帖子

为什么C编译器会优化开关,如果有所不同

当我偶然发现一个奇怪的问题时,我正在从事一个个人项目。

在一个非常紧密的循环中,我有一个整数,其值在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)

c optimization gcc bit-manipulation disassembly

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

Makefile使用Shell创建变量

我使用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是'归零'我的变量.知道什么是错的吗?

bash makefile gnu-make

8
推荐指数
1
解决办法
7937
查看次数

在网格中合并pdf

我有数百个代表纸牌游戏纸牌的 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?

linux printing pdf merge command-line-interface

5
推荐指数
0
解决办法
541
查看次数

Ada抑制无法访问的代码或缺少返回

我有一个实现许多功能的标记类型。在一种情况下,我需要这些功能之一来进入无限循环。不幸的是,据我所知,我没有办法对其进行编译,从而不会发出警告。我希望仍然使用-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)但是仍然对代码无法到达或缺少返回语句错误提出警告。

有什么办法可以使一次性功能永久运行而不会发出警告?

ada unreachable-code gnat

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

在Alpine Linux Docker容器中构建GNATCOLL

我似乎无法让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)

ada gnat docker musl alpine-linux

4
推荐指数
1
解决办法
130
查看次数

阿达的阐述根本没有发生

我有一个不寻常的情况,根本没有执行精简代码.这不是详细说明问题,而是所有问题的详细阐述.

问题在于我没有"讨论"有关的单位,但理论上它仍然应该是可访问的,只要它的详细说明发生.

当然,我可以为相关单元添加一个无用的"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 gnat

2
推荐指数
1
解决办法
138
查看次数

Ada Makefile绑定问题

我正在研究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)

makefile ada gnat

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

分析 GPRBuild

我有一个基于 GPR 的大型项目,编译可能需要 30 多分钟。

在分析了构建过程后,我注意到许多明显的低效率(多次调用 gprbuild 而不是聚合、过度使用替代文件而不是配置等)。我想知道是否有一些方法可以“分析”构建过程以查看需要这么长时间。

特别是即使是单个文件发生变化并且出现错误时,重新编译也需要大约5分钟。从理论上讲,应该很快意识到必须重新编译该文件(这是唯一一个这样做的)并开始编译过程,迅速发现错误。

从详细的输出来看,解析用于定义构建的大量 gpr 文件网络似乎需要相当长的时间,但我想知道它大部分时间都花在了哪里。

因此我的问题是:是否可以分析由 gprbuild 完成的构建?如果是这样,如何?

ada gprbuild

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

在mmap中执行代码以生成可执行代码段错误

我正在尝试编写一个复制函数的函数(并最终修改其程序集)并返回它.这适用于一个级别的间接,但在两个我得到段错误.

这是一个最小(非)工作示例:

#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)

c linux assembly function-pointers currying

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

Ada标记比较会导致编译器崩溃

我不确定这是我的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)

gcc ada segmentation-fault gnat

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