AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / 问题

All perguntas(coding)

Martin Hope
White Owl
Asked: 2025-04-22 04:32:03 +0800 CST

Obtenha o máximo de enum em C puro

  • 11

Supondo que eu tenha um código como este:

#include <stdio.h>

// A numbered enum with gaps
#define COLORS(X)  \
    X(RED,    10)  \
    X(GREEN,  2)   \
    X(BLUE,   5)   \
    X(YELLOW, 7)

typedef enum {
#define XX(N, M) CLR_##N = M,
    COLORS(XX)
#undef XX
} colors_e;

// This define must have the highest value of enum
#define MAX_COLOR_CODE 10 

typedef struct {
    char *language;
    // the define is needed for array definition inside a struct
    char *colors[MAX_COLOR_CODE + 1];
} color_names_t;

// The array of struct is selectively filled at compile time, hence use of enum for indexing
color_names_t color_names[] = {
    {"en", {[CLR_RED] = "red", [CLR_BLUE] = "blue", [CLR_GREEN] = "green"}},
    {"du", {[CLR_BLUE] = "blau", [CLR_YELLOW] = "gelb", [CLR_RED] = "rot"}},
};


/// ---- a sample usage of the defined array of structs

#define ARR_SIZE(X) (sizeof(X)/sizeof(X[0]))

int main() {
    for(int lidx=0; lidx<ARR_SIZE(color_names); lidx++) {
        printf("Language: %s\n", color_names[lidx].language);

        for(int idx=0; idx<ARR_SIZE(color_names[0].colors); idx++) {
            if(color_names[lidx].colors[idx])
                printf("\t%s\n", color_names[lidx].colors[idx]);
        }
    }

    return 0;
}

Existe uma maneira de calcular automaticamente uma MAX_COLOR_CODEdefinição?

c
  • 4 respostas
  • 174 Views
Martin Hope
user30256092
Asked: 2025-04-14 23:01:04 +0800 CST

Removendo elementos com base em valores de dicionário aninhados

  • 11

Tenho uma estrutura complexa de dicionário aninhado e preciso remover elementos com base nos valores de um dicionário aninhado. Meu dicionário se parece com isto:

my_dict = {
    'item1': {'name': 'Apple', 'price': 1.0, 'category': {'id': 1, 'name': 'Fruit'}},
    'item2': {'name': 'Banana', 'price': 0.5, 'category': {'id': 1, 'name': 'Fruit'}},
    'item3': {'name': 'Carrot', 'price': 0.75, 'category': {'id': 2, 'name': 'Vegetable'}},
    'item4': {'name': 'Broccoli', 'price': 1.5, 'category': {'id': 2, 'name': 'Vegetable'}}
}

Quero filtrar este dicionário para incluir apenas itens pertencentes à categoria "Fruta". Tentei o seguinte código:

new_dict = {}
for key, value in my_dict.items():
    if value['category']['name'] == 'Fruit':
        new_dict[key] = value
print(new_dict)

Isso funciona, mas estou me perguntando se há uma maneira mais concisa ou Pythonica de fazer isso, talvez usando compreensão de dicionário ou uma função de filtragem como filter().

python
  • 4 respostas
  • 496 Views
Martin Hope
Julie Johnson
Asked: 2025-04-09 21:56:30 +0800 CST

Como analisar corretamente os tempos de execução de chamadas do sistema a partir da saída strace usando pipes em C?

  • 11

Estou trabalhando em uma tarefa de programação de sistema operacional para entender pipes. texto A tarefa envolve o uso de expressões regulares para extrair informações da saída do strace e tempos de execução de chamadas de sistema estatísticos.

No entanto, estou enfrentando problemas com o cálculo incorreto dos tempos. Suspeito que a função parse_strace_line não esteja analisando corretamente as linhas de saída do strace, especialmente a parte do carimbo de data/hora (por exemplo, <0,000123>), resultando em valores de tempo incorretos ou ausentes nas estatísticas. A função pode não estar lidando corretamente com o formato da linha, com casos extremos como linhas incompletas, ou com o padrão regex, que pode não capturar com precisão o componente de tempo da saída do strace.

Meu ambiente é o Ubuntu rodando no WSL2.

Aqui está o código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <regex.h>

#define MAX_SYSCALLS 1024  // Maximum distinct syscalls we can track
#define TOP_N 5            // Number of top results to display

/* Syscall tracking structure
 * name: syscall name (e.g., "open", "read")
 * time: accumulated time spent in this syscall (seconds)
 */
typedef struct {
    char name[64];
    double time;
} syscall_stat;

/* Main statistics container
 * stats: array of individual syscall metrics
 * count: number of unique syscalls tracked
 * total_time: sum of all syscall times for percentage calculation
 */
typedef struct {
    syscall_stat stats[MAX_SYSCALLS];
    int count;
    double total_time;
} syscall_stats;

/* Parse a line of strace output with timing information (-T option)
 * line: input string from strace output
 * syscall_name: output parameter for extracted syscall name
 * time: output parameter for extracted duration
 * Returns: 1 if successful, 0 if line doesn't contain timing info
 * 
 * Strace line format examples:
 * openat(AT_FDCWD, "/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000014>
 * read(0, "hello\n", 1024)               = 6 <0.000010>
 */
int parse_strace_line(char* line, char* syscall_name, double* time) {
    // Filter lines without timing information
    if (strstr(line, " = ") == NULL || strstr(line, "<") == NULL) {
        return 0;
    }

    // Regular expression pattern breakdown:
    // ^(\w+)       Capture group 1: syscall name at line start
    // \(.*?\)      Non-greedy match of arguments between parentheses
    // \s+=\s+.*?   Match return value portion
    // <(\d+\.?\d*)> Capture group 2: time value between <>
    regex_t regex;
    regcomp(&regex, "^(\\w+)\\(.*?\\)\\s+=\\s+.*?<(\\d+\\.?\\d*)>$", REG_EXTENDED);
    regmatch_t matches[3];  // Array for regex capture groups

    if (regexec(&regex, line, 3, matches, 0) != 0) {
        regfree(&regex);
        return 0;
    }

    // Extract syscall name from first capture group
    int name_len = matches[1].rm_eo - matches[1].rm_so;
    strncpy(syscall_name, line + matches[1].rm_so, name_len);
    syscall_name[name_len] = '\0';

    // Convert time string to double
    char* time_str = line + matches[2].rm_so;
    *time = atof(time_str);

    regfree(&regex);
    return 1;
}

/* Update statistics with new syscall data
 * stats: pointer to statistics container
 * name: syscall name to add/update
 * time: duration to accumulate
 * 
 * If the syscall already exists, we sum the time.
 * If new, we add it to the list (until MAX_SYSCALLS).
 */
void add_syscall(syscall_stats *stats, const char *name, double time) {
    // Safety check against array overflow
    if (stats->count >= MAX_SYSCALLS) {
        fprintf(stderr, "Warning: Reached maximum tracked syscalls (%d)\n", MAX_SYSCALLS);
        return;
    }

    // Check existing entries for duplicate syscall
    for (int i = 0; i < stats->count; i++) {
        if (strcmp(stats->stats[i].name, name) == 0) {
            stats->stats[i].time += time;
            stats->total_time += time;
            return;
        }
    }

    // Add new entry if space available
    if (stats->count < MAX_SYSCALLS) {
        strncpy(stats->stats[stats->count].name, name, sizeof(stats->stats[0].name));
        stats->stats[stats->count].time = time;
        stats->total_time += time;
        stats->count++;
    }
}

/* Display top N syscalls by accumulated time
 * stats: statistics container with all data
 * n: number of top results to show
 * 
 * Uses bubble sort for simplicity with small datasets.
 * Prints percentages relative to total tracked time.
 * Flushes output with nulls for clean pipe termination.
 */
void print_top_syscalls(syscall_stats *stats, int n) {
    if (stats->count == 0 || stats->total_time == 0) {
        fprintf(stderr, "Error: No valid syscall data to display\n");
        return;
    }

    // Simple O(n²) sort acceptable for MAX_SYSCALLS=1024
    for (int i = 0; i < stats->count - 1; i++) {
        for (int j = i+1; j < stats->count; j++) {
            // Swap if later entry has higher time
            if (stats->stats[j].time > stats->stats[i].time) {
                syscall_stat temp = stats->stats[i];
                stats->stats[i] = stats->stats[j];
                stats->stats[j] = temp;
            }
        }
    }

    // Determine number of results to display
    n = stats->count < n ? stats->count : n;
    for (int i = 0; i < n; i++) {
        double ratio = (stats->stats[i].time / stats->total_time) * 100;
        printf("%s (%d%%)\n", stats->stats[i].name, (int)ratio);
    }

    /* Null-terminate output for clean pipe communication
     * Some programs may read fixed buffer sizes - this ensures
     * we flush the pipe completely and avoid hanging readers */
    for (int i = 0; i < 80; i++) putchar('\0');
    fflush(stdout);
}

/* Main execution flow:
 * 1. Validate command line arguments
 * 2. Set up parent/child process communication
 * 3. Child: execute strace with command
 * 4. Parent: process and analyze strace output
 */
int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s COMMAND [ARGS...]\n", argv[0]);
        fprintf(stderr, "Example: %s ls -l\n", argv[0]);
        return 1;
    }

    // Create pipe for inter-process communication
    int pipefd[2];
    if (pipe(pipefd) == -1) {
        perror("Failed to create pipe");
        return 1;
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("Process fork failed");
        return 1;
    }

    if (pid == 0) { // Child process - execute strace
        // Redirect stdout to pipe write end
        close(pipefd[0]);
        dup2(pipefd[1], STDOUT_FILENO);
        close(pipefd[1]);

        // Build strace argument array:
        // strace -T [user command] [args...]
        char* strace_argv[argc + 2];
        strace_argv[0] = "/usr/bin/strace";
        strace_argv[1] = "-T";  // Enable timing reports
        for (int i = 1; i < argc; i++) {
            strace_argv[i+1] = argv[i];
        }
        strace_argv[argc+1] = NULL;  // NULL-terminate array

        // Execute strace with clean environment
        execve("/usr/bin/strace", strace_argv, (char *[]){ "PATH=/bin:/usr/bin", NULL });
        perror("Failed to execute strace");
        return 1;
    } else { // Parent process - analyze output
        close(pipefd[1]);  // Close unused write end
        syscall_stats stats = {0};  // Initialize all fields to zero

        char buffer[1024];
        char* line_start = buffer;
        ssize_t bytes_read;

        // Read output in chunks until EOF
        while ((bytes_read = read(pipefd[0], 
               line_start, 
               sizeof(buffer) - (line_start - buffer))) > 0) {
            // Null-terminate the received data
            buffer[bytes_read + (line_start - buffer)] = '\0';
            line_start = buffer;

            // Process complete lines (delimited by newlines)
            char* line_end;
            while ((line_end = strchr(line_start, '\n')) != NULL) {
                *line_end = '\0';  // Temporarily terminate at newline

                char syscall_name[64];
                double time;
                if (parse_strace_line(line_start, syscall_name, &time)) {
                    add_syscall(&stats, syscall_name, time);
                }

                line_start = line_end + 1;  // Move to next line
            }

            // Handle partial line remaining in buffer
            if (line_start != buffer) {
                size_t remaining = buffer + sizeof(buffer) - line_start;
                // Move partial line to buffer start for next read
                memmove(buffer, line_start, remaining);
                line_start = buffer + remaining;
            }
        }

        // Cleanup and display results
        close(pipefd[0]);
        wait(NULL);  // Wait for strace to terminate completely
        print_top_syscalls(&stats, TOP_N);
    }

    return 0;
}

Esta é a linha de comando para teste:

root@DimLights:/mnt/f/WSL/Data/OperatingSystems/2025/os2025/sperf# gcc -g -o sperf sperf.c -lm -lrt
root@DimLights:/mnt/f/WSL/Data/OperatingSystems/2025/os2025/sperf# ./sperf echo "Hello WSL"

execve("/bin/echo", ["echo", "Hello WSL"], 0x7ffe6258ee20 /* 1 var */) = 0 <0.000363>
brk(NULL)                               = 0x55d4dee1c000 <0.000104>
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f483b684000 <0.000137>
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory) <0.000115>
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000133>
fstat(3, {st_mode=S_IFREG|0644, st_size=36191, ...}) = 0 <0.000115>
mmap(NULL, 36191, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f483b67b000 <0.000097>
close(3)                                = 0 <0.000079>
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000108>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\243\2\0\0\0\0\0"..., 832) = 832 <0.000094>
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 <0.000101>
fstat(3, {st_mode=S_IFREG|0755, st_size=2125328, ...}) = 0 <0.000096>
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 <0.000088>
mmap(NULL, 2170256, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f483b469000 <0.000107>
mmap(0x7f483b491000, 1605632, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7f483b491000 <0.000117>
mmap(0x7f483b619000, 323584, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b0000) = 0x7f483b619000 <0.000099>
mmap(0x7f483b668000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1fe000) = 0x7f483b668000 <0.000102>
mmap(0x7f483b66e000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f483b66e000 <0.000103>
close(3)                                = 0 <0.000104>
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f483b466000 <0.000085>
arch_prctl(ARCH_SET_FS, 0x7f483b466740) = 0 <0.000049>
set_tid_address(0x7f483b466a10)         = 1543 <0.000319>
set_robust_list(0x7f483b466a20, 24)     = 0 <0.000098>
rseq(0x7f483b467060, 0x20, 0, 0x53053053) = 0 <0.000123>
mprotect(0x7f483b668000, 16384, PROT_READ) = 0 <0.000096>
mprotect(0x55d4de99a000, 4096, PROT_READ) = 0 <0.000093>
mprotect(0x7f483b6bc000, 8192, PROT_READ) = 0 <0.000103>
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0 <0.000095>
munmap(0x7f483b67b000, 36191)           = 0 <0.000118>
getrandom("\xc0\x8d\xa3\xbc\x88\x59\xbb\xd3", 8, GRND_NONBLOCK) = 8 <0.000098>
brk(NULL)                               = 0x55d4dee1c000 <0.000113>
brk(0x55d4dee3d000)                     = 0x55d4dee3d000 <0.000097>
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 <0.000092>
write(1, "Hello WSL\n", 10Received from pipe: Hello WSL
)             = 10 <0.000216>
close(1)                                = 0 <0.000165>
close(2)                                = 0 <0.000092>
exit_group(0)                           = ?
+++ exited with 0 +++
Total count is zero

Aqui está o que eu tentei e o que eu esperava: usei a depuração do GDB e notei que o loop while ((line = strchr(line_start, '\n')) != NULL) foi executado apenas uma vez ao testar o comando. Não consigo entender por que a saída mostra +++ exited with 0 +++ e Total count is zero. Também pedi ajuda à IA e modifiquei partes da função parse_strace_line e o padrão de expressão regular, mas com pouco sucesso.

O que realmente aconteceu: As estatísticas permanecem vazias (a contagem total é zero), indicando que a análise ou extração de dados falhou.

O que eu esperava: O código deveria analisar corretamente os registros de data e hora das chamadas do sistema a partir da saída do strace, acumular seus tempos e calcular a proporção do tempo de cada chamada em relação ao total.

Como estudante, eu agradeceria muito se você pudesse apontar os erros no meu código e explicar como ler corretamente os tempos de chamada do sistema e convertê-los na proporção.

c
  • 1 respostas
  • 97 Views
Martin Hope
Mark Theis
Asked: 2025-04-05 07:37:13 +0800 CST

Por que usar índices de array uint64_t em vez de uint32_t simplifica a saída do compilador?

  • 11

Se eu tiver um array, ou um ponteiro para um array, do tipo uint32_t, meus arrays são quase sempre menores em comprimento do que o máximo que eu precisaria indexar com um uint32_t. No entanto, descobri que ao usar uint64_tem vez de uint32_tcomo um índice, o compilador evita algumas movinstruções.

Aqui está um exemplo muito simples para ilustrar isso:

Código fonte:

#include <cstdint>

void set_value(uint32_t* __restrict array, const uint32_t idx, const uint32_t value)
{
    array[idx] = value;
}

void set_value(uint32_t* __restrict array, const uint64_t idx, const uint32_t value)
{
    array[idx] = value;
}

Montagem gerada usando Clang 14.0.0 com -O3 -march=skylake -std=c++17 -mno-vzeroupper:

set_value(unsigned int*, unsigned int, unsigned int):
  mov eax, esi
  mov dword ptr [rdi + 4*rax], edx
  ret

set_value(unsigned int*, unsigned long, unsigned int):
  mov dword ptr [rdi + 4*rsi], edx
  ret

Alguém pode explicar as diferentes saídas do compilador? Por que a uint64_tversão pula a movinstrução?

c++
  • 1 respostas
  • 154 Views
Martin Hope
peterW
Asked: 2024-06-20 08:04:46 +0800 CST

Como executo pandas cumsum enquanto pulo linhas duplicadas em outro campo?

  • 12

Estou tentando usar a função pandas.cumsum(), mas de uma forma que ignora linhas com um valor na coluna ID que está duplicado e especificamente adiciona apenas o último valor à soma cumulativa, ignorando todos os valores anteriores. Exemplo de código abaixo (não consegui compartilhar o código real, que é para trabalho).

import pandas as pd, numpy as np
import random as rand
id = ['a','b','c','a','b','e','f','a','b','k']
value = [12,14,3,13,16,7,4,6,10,18]

df = pd.DataFrame({'id':id, 'value':value})
df["cumsum_of_value"] = df['value'].cumsum()
df["desired_output"] = [
    12,26,29,30,32,39,43,36,30,48
]
df["comments"] = [""]*len(df)
df.loc[df.index==0, "comments"]="standard cumsum"
df.loc[df.index==1, "comments"]="standard cumsum"
df.loc[df.index==2, "comments"]="standard cumsum"
df.loc[df.index==3, "comments"]="cumsum of rows 1-3, ignore row 0"
df.loc[df.index==4, "comments"]="cumsum of rows 2-4, ignore rows 0, 1"
df.loc[df.index==5, "comments"]="cumsum of rows 2-5, ignore rows 0, 1"
df.loc[df.index==6, "comments"]="cumsum of rows 2-6, ignore rows 0, 1"
df.loc[df.index==7, "comments"]="cumsum of rows 2,4-7, ignore rows 0, 1, 3"
df.loc[df.index==8, "comments"]="cumsum of rows 2,5-8, ignore rows 0, 1, 3, 4"
df.loc[df.index==9, "comments"]="cumsum of rows 2,5-9, ignore rows 0, 1, 3, 4"
print(df)

Neste exemplo, existem sete (7) valores exclusivos na coluna ID (a, b, c, d, e, f, g), portanto, o cumsum deve somar no máximo sete (7) registros como sua saída em qualquer linha.

Isso é possível usando combinações de funções como cumsum(), groupby(), duplicado(), drop_duplicates() e evitando o uso de um loop iterativo?

Eu tentei o abaixo

df["duped"] = np.where(df["id"].duplicated(keep='last'),0,1)
df["value_duped"] = df["duped"] * df["value"]
df["desired_output_attempt"] = df["cumsum_of_value"] - df["value_duped"]

Mas não chega perto da resposta correta. Não consigo pensar em como fazer algo assim resultar na saída desejada sem iterar.

python
  • 4 respostas
  • 121 Views
Martin Hope
Maël
Asked: 2024-05-29 16:08:14 +0800 CST

Nome dinâmico com cola na chamada mutada

  • 12

Quero criar uma função que tome como primeiro argumento o nome de um conjunto de dados e, como segundo argumento, parte do nome de uma coluna do dataframe. Quero então usar gluepara construir dinamicamente o nome da coluna, na função, e usar essa coluna em uma mutatechamada, assim:

library(tidyverse)

tmp <- 
  function(data, type){
  var <- glue::glue("Sepal.{type}")
  iris |> 
    select({{var}}) |> 
    mutate("{var}" := mean({{var}}))
}

Eu tentei muitas coisas, mas tenho dificuldade em encontrar uma solução em que a coluna seja chamada tanto pelo nome da nova coluna (aqui, "{var}") quanto pelo cálculo da nova coluna (aqui, mean({{var}})). O que se deve fazer nesses casos?

Aqui, a chamada tmp(iris, "Length")deve retornar um 150x1data.frame com o valor médio em todas as linhas.

tidyversesolução são preferidas ou quaisquer respostas baseadas em pipe.

  • 3 respostas
  • 283 Views
Martin Hope
ChrisB
Asked: 2024-04-23 23:59:49 +0800 CST

Por que uma função que recebe um valor std::unique_ptr by não chama o destruidor no gcc/clang? [duplicado]

  • 12
Esta pergunta já tem respostas aqui :
Destruição tardia de parâmetros de função (3 respostas)
Fechado há 2 horas .

Observando a saída do assembly da seguinte função C++ simples:

#include <memory>
int square(std::unique_ptr<int> num) {
    return *num * *num;
}

Gcc e clang emitem o seguinte assembly ( -O2):

square(std::unique_ptr<int, std::default_delete<int> >):
        mov     rax, QWORD PTR [rdi]
        mov     eax, DWORD PTR [rax]
        imul    eax, eax
        ret

Isso foi muito inesperado para mim: para onde o destruidor está sendo chamado?

O MSVC, por outro lado, faz o que eu esperava e chama o destruidor.

Aqui está uma reprodução de godbolt: https://godbolt.org/z/e66xh9Yos

Também tentei usar tipos maiores intpara ver se é alguma otimização de tamanho pequeno, mas não pareceu ser o caso.

Alguém pode explicar o que está acontecendo aqui?

c++
  • 1 respostas
  • 100 Views
Martin Hope
TartanLlama
Asked: 2024-02-20 05:42:03 +0800 CST

Onde é especificada a ordem em que as realocações ELF são aplicadas?

  • 12

Considere os dois arquivos a seguir em um sistema Linux:

use_message.cpp

#include <iostream>

extern const char* message;
void print_message();

int main() {
    std::cout << message << '\n';
    print_message();
}

libmessage.cpp

#include <iostream>
const char* message = "Meow!";

void print_message() {
    std::cout << message << '\n';
}

Podemos compilar use_message.cpp em um arquivo objeto, compilar libmessage.cpp em uma biblioteca compartilhada e vinculá-los, assim:

$ g++ use_message.cpp -c -pie -o use_message.o
$ g++ libmessage.cpp -fPIC -shared -o libmessage.so
$ g++ use_message.o libmessage.so -o use_message

A definição de messageoriginalmente reside em libmessage.so . Quando use_messageé executado, o vinculador dinâmico executa realocações que:

  1. Atualize a messagedefinição dentro de libmessage.so com o endereço de carregamento dos dados da string
  2. Copie a definição messagede libmessage.so para a seção use_message.bss
  3. Atualize a tabela de deslocamento global em libmessage.so para apontar para a nova versão de messagedentro de use_message

As realocações relevantes, conforme descartadas por readelf, são:

usar_mensagem

  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000004150  000c00000005 R_X86_64_COPY     0000000000004150 message + 0

Esta é a realocação número 2 na lista que escrevi antes.

libmessage.so

  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000004040  000000000008 R_X86_64_RELATIVE                    2000
000000003fd8  000b00000006 R_X86_64_GLOB_DAT 0000000000004040 message + 0

Estes são os números de realocação 1 e 3, respectivamente.

Há uma dependência entre os números de realocação 1 e 2: a atualização para a definição de libmessage.somessage deve acontecer antes que esse valor seja copiado para use_message , caso contrário, use_message não apontará para o local correto.

Minha pergunta é: como é especificada a ordem de aplicação das remanejamentos? Existe algo codificado nos arquivos ELF que especifica isso? Ou na ABI? Ou espera-se apenas que o vinculador dinâmico resolva as dependências entre as realocações e garanta que todas as realocações que gravam em um determinado endereço de memória sejam executadas antes de qualquer realocação que seja lida no mesmo local? O vinculador estático gera apenas realocações de modo que as do executável sempre possam ser processadas após as da biblioteca compartilhada?

c++
  • 1 respostas
  • 508 Views
Martin Hope
pablo1977
Asked: 2024-02-07 21:40:23 +0800 CST

Existência ou não de long_double_t (padrão C:C23)

  • 12

A nova norma C (ISO/IEC 9899:2023, também conhecida como C23),
no Anexo H, são definidas diversas macros e tipos,
relativos à aritmética real e complexa,
sujeitos à norma ISO/IEC 60559 (aritmética de ponto flutuante).

De acordo com a subseção H.1, existem três
macros definidas pela implementação para testar a conformidade
com as definições do Anexo H.

__STDC_IEC_60559_TYPES__  
__STDC_IEC_60559_BFP__  
__STDC_IEC_60559_DFP__  

Além disso, para “ativar” as macros e tipos associados,
o usuário deve definir a macro:

__STDC_WANT_IEC_60559_TYPES_EXT__  

A redação da norma é clara em vários detalhes:

  • Se __STDC_IEC_60559_BFP__for definido pelo compilador, isso implica que _FloatNe _FloatN_toutros _FloatN*tipos são definidos.
  • Se __STDC_IEC_60559_DFP__for definido pelo compilador, isso implica que _DecimalNe _DecimalN_toutros _DecimalN*tipos são definidos.
  • Em ambos os casos, a macro __STDC_IEC_60559_TYPES__está definida.
  • Se a macro __STDC_IEC_60559_TYPES__estiver definida, significa que pelo menos uma das macros __STDC_IEC_60559_BFP__ou __STDC_IEC_60559_DFP__(ou ambas) está definida.

Na subseção H.11, o tipo long_double_té adicionado a <math.h>.

No entanto, não consigo deduzir em que condições se pode garantir a existência de long_double_tuma determinada implementação.

PERGUNTA:

Se __STDC_IEC_60559_TYPES__estiver definido, é suficiente ter certeza de que long_double_ttambém está definido em <math.h>?

Minha dúvida vem do seguinte caso particular que pode surgir:

  • __STDC_IEC_60559_TYPES__e __STDC_IEC_60559_DFP__estão definidos, mas __STDC_IEC_60559_BFP__não estão definidos.

Neste caso, os tipos decimais são definidos.
No entanto, long_double_tnão é um tipo decimal.

SUBLEMA:
A macro __STDC_IEC_60559_BFP__deve existir para garantir a existência de long_double_t?

COMENTÁRIOS:

Como @John Bollinger explica em sua resposta,
a existência de *BFP__e/ou *DFP__macros
apenas garante que _FloatNexistam _DecimalNpara certos valores pequenosN de .
(Eu estava ciente desse detalhe, mas minha explicação não foi a melhor.)

Link para um rascunho padrão do C23

c
  • 1 respostas
  • 98 Views
Martin Hope
Michael A
Asked: 2023-11-11 01:13:05 +0800 CST

formato fmt %H:%M:%S sem decimais

  • 12

Estou tentando formatar um std::chrono::durationobjeto no formato HH:MM::SS, por exemplo, 16:42:02 sendo as horas (16), os minutos (42) e os segundos (2).

a biblioteca fmtoferece especificadores de formatação úteis para isso:

using namespace std::chrono;

auto start = high_resolution_clock::now();
auto end = start + 4s;
fmt::print("{:%H:%M:%S} \n", end);

que infelizmente imprime os segundos em decimais

16:58:55.359425076 

Quero arredondar para o número inteiro mais próximo, mas não consigo descobrir onde colocar o especificador de precisão (precisão 2 apenas em termos de teste):

fmt::print("{:.2%H:%M:%S} \n", end);  // error
fmt::print("{:.2f%H:%M:%S} \n", end);  // error 
fmt::print("{:%H:%M:.2%S} \n", end);  // nonsense: 17:07:.202.454873454 

Estou um pouco perdido olhando para os detalhes da especificação do formato do cronômetro...

Um exemplo de explorador de compilador acima está aqui .

c++
  • 1 respostas
  • 78 Views
Prev
Próximo

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve