RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-210482

Rikitikitavi's questions

Martin Hope
Rikitikitavi
Asked: 2024-03-18 03:47:25 +0000 UTC

如何设置项目版本

  • 5

运行命令时如何设置项目版本cmake?

有CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(my_project LANGUAGES CXX)

message("PROJECT_NAME=${PROJECT_NAME}")
message("my_project_VERSION_MAJOR=${my_project_VERSION_MAJOR}")

我尝试通过参数传递它:

cmake . -Dmy_project_VERSION_MAJOR=2

noproject()重置此变量。运行时,cmake输出如下:

PROJECT_NAME=my_project
my_prject_VERSION_MAJOR=

版本是通过计算出来的 git rev-list HEAD | wc -l,所以我不想显式地写在CMakeLists.txt.

cmake
  • 1 个回答
  • 21 Views
Martin Hope
Rikitikitavi
Asked: 2024-02-07 02:45:18 +0000 UTC

使用shared_ptr时的数据竞争

  • 6

在 Rainer Grimm 的书中, Concurrency with Modern C++这些代码行:

std::shared_ptr<int> ptr = std::make_shared<int>(2011);

for (auto i=0; i<10; i++){ 
    std::thread([&ptr]{
                        ptr = std::make_shared<int>(2014); 
                      }
               ).detach();
}

有一个说法:

lambda 函数通过引用绑定第 4 行中的 std::shared_ptr ptr。这意味着,赋值(第5行)可能会变成底层资源的并发读写;因此,该程序具有未定义的行为。

告诉我为什么行为会是未定义的?在我看来,这与cppreference相矛盾

所有成员函数(包括复制构造函数和复制赋值)都可以由共享_ptr 的不同实例上的多个线程调用,而无需额外的同步,即使这些实例是同一对象的副本并共享所有权。

c++
  • 1 个回答
  • 35 Views
Martin Hope
Rikitikitavi
Asked: 2023-08-04 00:31:54 +0000 UTC

模板类专业化

  • 7

有这样一个带有两个模板参数的模板类:

template <class T1, class T2>
class A
{
public:

    void f()
    {
        t1 = t2.get();
    }

    T1 result() {return t1;}
private:
    T1 t1;
    T2 t2;
};

是否可以为一个模板参数编写此类的特化:如下所示:

template<class T1> 
class A<T1>
{

    void f() {/*do nothing*/}
    T1 result() {return t1;}

public:
    T1 t1;
};

但在这种形式下它不起作用,编译器需要两个参数。

你可以这样做:

template<class T1> 
class A<T1, void>
{

    void f() {/*do nothing*/}
    T1 result() {return t1;}

public:
    T1 t1;
};

但我不喜欢使用 write void:

A<int, void> a;

我想简单写一下

A<int> a;
c++
  • 1 个回答
  • 26 Views
Martin Hope
Rikitikitavi
Asked: 2022-03-26 23:41:50 +0000 UTC

haskell 中的函数

  • 1

有这段代码,它试图描述一个机器人对象:

robot (name, attack, hp) = \message -> message(name, attack, hp)

name (n, _, _) = n
attack (_, a, _) = a
hp (_, _, hp) = hp

getAttack aRobot = aRobot attack
getHP aRobot = aRobot hp
getName aRobot = aRobot name

setName aRobot newName = aRobot(\(n, a, h) -> robot(newName, a , h))
setAttack aRobot newAttack = aRobot(\(n, a, h) -> robot(n, newAttack , h))
setHP aRobot newHP = aRobot(\(n, a, h) -> robot(n, n , newHP))

printRobot aRobot = aRobot( \(n, a, h) -> n ++ " attack: " ++ (show a) ++ " hp: " ++ (show h) )

damage aRobot dmg = aRobot(\(n,a,h) -> robot(n,a, h - dmg))

fight aRobot defender = damage defender dmg
    where dmg = if getHP aRobot > 0
                then getAttack aRobot
                else 0

getAllHP aRobots = map getHP aRobots

现在我需要编写一个函数,在一轮后返回两个机器人的元组,我这样做:

oneRoundFight aR1 aR2 = ( fight aR1 aR2, fight aR2 aR1 )

一个错误:

*Main> :l robot.hs
[1 of 1] Compiling Main             ( robot.hs, interpreted )

robot.hs:27:48: error:
    * Occurs check: cannot construct the infinite type:
        b2 ~ ((a2, b2, b1) -> t1) -> t1
      Expected type: ((a2, ((a2, b2, b1) -> t1) -> t1,
                       ((a2, b2, b1) -> t1) -> t1)
                      -> ((a2, b2, b1) -> t1) -> t1)
                     -> a1
        Actual type: ((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1
    * In the first argument of `fight', namely `aR2'
      In the expression: fight aR2 aR1
      In the expression: (fight aR1 aR2, fight aR2 aR1)
    * Relevant bindings include
        aR2 :: ((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1
          (bound at robot.hs:27:19)
        aR1 :: ((a, ((a, b, a1) -> t) -> t, ((a, b, a1) -> t) -> t)
                -> ((a, b, a1) -> t) -> t)
               -> b1
          (bound at robot.hs:27:15)
        oneRoundFight :: (((a, ((a, b, a1) -> t) -> t,
                            ((a, b, a1) -> t) -> t)
                           -> ((a, b, a1) -> t) -> t)
                          -> b1)
                         -> (((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1)
 -> (a1, b1)
          (bound at robot.hs:27:1)
   |
27 | oneRoundFight aR1 aR2 = ( fight aR1 aR2, fight aR2 aR1 )
   |                                                ^^^

robot.hs:27:52: error:
    * Occurs check: cannot construct the infinite type:
        b ~ ((a, b, a1) -> t) -> t
      Expected type: ((a, b, a1) -> ((a, b, a1) -> t) -> t) -> b1
        Actual type: ((a, ((a, b, a1) -> t) -> t, ((a, b, a1) -> t) -> t)
                      -> ((a, b, a1) -> t) -> t)
                     -> b1
    * In the second argument of `fight', namely `aR1'
      In the expression: fight aR2 aR1
      In the expression: (fight aR1 aR2, fight aR2 aR1)
    * Relevant bindings include
        aR2 :: ((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1
          (bound at robot.hs:27:19)
        aR1 :: ((a, ((a, b, a1) -> t) -> t, ((a, b, a1) -> t) -> t)
                -> ((a, b, a1) -> t) -> t)
               -> b1
          (bound at robot.hs:27:15)
        oneRoundFight :: (((a, ((a, b, a1) -> t) -> t,
                            ((a, b, a1) -> t) -> t)
                           -> ((a, b, a1) -> t) -> t)
                          -> b1)
                         -> (((a2, b2, b1) -> ((a2, b2, b1) -> t1) -> t1) -> a1)
 -> (a1, b1)
          (bound at robot.hs:27:1)
   |
27 | oneRoundFight aR1 aR2 = ( fight aR1 aR2, fight aR2 aR1 )
   |                                                    ^^^
Failed, no modules loaded.
Prelude>

我不太明白这个输出是什么意思,特别是cannot construct the infinite type: ,如果你改变地方的参数:( fight aR1 aR2, fight aR1 aR2 )那么这个错误就不会发生。

你能解释一下吗?

同时,函数fight编写并工作:

Prelude> :l robot.hs
[1 of 1] Compiling Main             ( robot.hs, interpreted )
Ok, one module loaded.
*Main> aR1 = robot("r1", 8, 100)
*Main> aR2 = robot("r2", 4, 120)
*Main> aR2_damaged = fight aR1 aR2
*Main> aR1_damaged = fight aR2 aR1
*Main> printRobot aR1_damaged
"r1 attack: 8 hp: 96"
*Main> printRobot aR2_damaged
"r2 attack: 4 hp: 112"
haskell
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2022-05-12 00:24:50 +0000 UTC

在汇编程序中添加数字

  • 0

有一个程序读取两个数字,将它们相加并打印结果:

    SYS_EXIT equ 1
    SYS_READ equ 3
    SYS_WRITE equ 4
    STDIN equ 0
    STDOUT equ 1
    
    

section .text
    global _start

_start:
    mov edx, len1
    mov ecx, msg1
    mov ebx, STDOUT
    mov eax, SYS_WRITE
    int 0x80

    mov ecx, numX
    mov edx, 2
    mov ebx, STDIN
    mov eax, SYS_READ
    int 0x80
    

    mov edx, len2
    mov ecx, msg2
    mov ebx, STDOUT
    mov eax, SYS_WRITE
    int 0x80

    mov ecx, numY
    mov edx, 2
    mov ebx, STDIN
    mov eax, SYS_READ
    int 0x80

    mov eax, [numX]
    sub eax, '0'

    mov ebx, [numY]
    sub ebx, '0'

    add eax, ebx
    add eax, '0'

    mov [res], eax

    mov eax, SYS_WRITE
    mov ebx, STDOUT
    mov ecx, res
    mov edx, 2
    int 0x80

    mov eax, SYS_WRITE
    mov ebx, STDOUT
    mov ecx, msg4
    mov edx, len4
    int 0x80

    
    mov eax,SYS_EXIT
    int 0x80

section .data
    msg1 db 'X=',
    len1 equ $-msg1
    msg2 db 'Y=',
    len2 equ $-msg2
    msg3 db 'X+Y='
    len3 equ $-msg3
    msg4 db 0xA, 0xB
    len4 equ 2


segment .bss
    numX resb 2
    numY resb 2
    res resb 1

这是它显示的内容objdump -D

app:     file format elf32-i386


Disassembly of section .text:

08049000 <.text>:
 8049000:   ba 02 00 00 00          mov    $0x2,%edx
 8049005:   b9 00 a0 04 08          mov    $0x804a000,%ecx
 804900a:   bb 01 00 00 00          mov    $0x1,%ebx
 804900f:   b8 04 00 00 00          mov    $0x4,%eax
 8049014:   cd 80                   int    $0x80
 8049016:   b9 0c a0 04 08          mov    $0x804a00c,%ecx
 804901b:   ba 02 00 00 00          mov    $0x2,%edx
 8049020:   bb 00 00 00 00          mov    $0x0,%ebx
 8049025:   b8 03 00 00 00          mov    $0x3,%eax
 804902a:   cd 80                   int    $0x80
 804902c:   ba 02 00 00 00          mov    $0x2,%edx
 8049031:   b9 02 a0 04 08          mov    $0x804a002,%ecx
 8049036:   bb 01 00 00 00          mov    $0x1,%ebx
 804903b:   b8 04 00 00 00          mov    $0x4,%eax
 8049040:   cd 80                   int    $0x80
 8049042:   b9 0e a0 04 08          mov    $0x804a00e,%ecx
 8049047:   ba 02 00 00 00          mov    $0x2,%edx
 804904c:   bb 00 00 00 00          mov    $0x0,%ebx
 8049051:   b8 03 00 00 00          mov    $0x3,%eax
 8049056:   cd 80                   int    $0x80
 8049058:   a1 0c a0 04 08          mov    0x804a00c,%eax
 804905d:   83 e8 30                sub    $0x30,%eax
 8049060:   8b 1d 0e a0 04 08       mov    0x804a00e,%ebx
 8049066:   83 eb 30                sub    $0x30,%ebx
 8049069:   01 d8                   add    %ebx,%eax
 804906b:   83 c0 30                add    $0x30,%eax
 804906e:   a3 10 a0 04 08          mov    %eax,0x804a010
 8049073:   b8 04 00 00 00          mov    $0x4,%eax
 8049078:   bb 01 00 00 00          mov    $0x1,%ebx
 804907d:   b9 10 a0 04 08          mov    $0x804a010,%ecx
 8049082:   ba 01 00 00 00          mov    $0x1,%edx
 8049087:   cd 80                   int    $0x80
 8049089:   b8 04 00 00 00          mov    $0x4,%eax
 804908e:   bb 01 00 00 00          mov    $0x1,%ebx
 8049093:   b9 08 a0 04 08          mov    $0x804a008,%ecx
 8049098:   ba 02 00 00 00          mov    $0x2,%edx
 804909d:   cd 80                   int    $0x80
 804909f:   b8 01 00 00 00          mov    $0x1,%eax
 80490a4:   cd 80                   int    $0x80

Disassembly of section .data:

0804a000 <.data>:
 804a000:   58                      pop    %eax
 804a001:   3d 59 3d 58 2b          cmp    $0x2b583d59,%eax
 804a006:   59                      pop    %ecx
 804a007:   3d                      .byte 0x3d
 804a008:   0a 0b                   or     (%ebx),%cl

Disassembly of section .bss:

0804a00c <.bss>:
    ...

这是调试器显示的内容:

(gdb) run
Starting program: /home/rikitikitavi/projects/asm/app 
X=5
Y=5

Breakpoint 1, 0x08049058 in ?? ()
(gdb) c
Continuing.

Breakpoint 2, 0x08049069 in ?? ()
(gdb) info registers
eax            0xa350a05           171248133
ecx            0x804a00e           134520846
edx            0x2                 2
ebx            0xa05               2565
esp            0xffffd140          0xffffd140
ebp            0x0                 0x0
esi            0x0                 0
edi            0x0                 0
eip            0x8049069           0x8049069
eflags         0x206               [ PF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x0                 0
(gdb) si
0x0804906b in ?? ()
(gdb) info registers
eax            0xa35140a           171250698
ecx            0x804a00e           134520846
edx            0x2                 2
ebx            0xa05               2565
esp            0xffffd140          0xffffd140
ebp            0x0                 0x0
esi            0x0                 0
edi            0x0                 0
eip            0x804906b           0x804906b
eflags         0x206               [ PF IF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x0                 0


从objdump地址可以看出0x08049069,有一个加法命令—— add %ebx,%eax。在执行此命令之前,寄存器中应该有必要的数字 5 和 5 eax,ebx相反,我分别看到了0xa350a05和0xa05。05最后,可以说,暗示寄存器包含我需要的东西,但其余的呢?- 我理解正确,05这是寄存器的内容,al其余bl的是垃圾?那么他是从哪里来的呢?

然后我将代码添加0到结果中,将其写入内存并输出。如果您输入4并且当您输入时,5那么一切正常:

rikitikitavi@rikitikitavi:~/projects/asm$ ./app 
X=4
Y=5
9

但如果你进入5然后5一切都打破了:

rikitikitavi@rikitikitavi:~/projects/asm$ ./app 
X=5
Y=5
:

我什至理解它为什么会中断 - 因为第二个数字出现在十进制系统中并且添加代码0并不完全正确(尽管结果,原则上,在 acsii 表:之后立即是正确的)。9我需要以某种方式将结果显示给我的朋友,但我不明白如何?

现在简短的问题:

  1. 为什么我在调试器中看到一些奇怪的寄存器值?
  2. 如何更改结果输出?
ассемблер
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2022-04-17 17:25:52 +0000 UTC

并行执行快速排序

  • 2

这是快速排序的实现:

template<class iterator>
void qsort(iterator begin, iterator end)
{
    if (begin == end)
        return;

    const auto distance = std::distance(begin, end);
    iterator p = std::next(begin, distance / 2);
    iterator it1 = std::partition(begin, end, [&p](const auto& v){ return v < *p;});
    iterator it2 = std::partition(it1, end, [&p](const auto& v) { return !(v > *p);});

    qsort(begin, it1);
    qsort(it2,  end);
}

我想实现这个算法的并行执行。你当然可以这样做:

template<class iterator>
void qsort(iterator begin, iterator end)
{
    if (begin == end)
        return;

    const auto distance = std::distance(begin, end);
    iterator p = std::next(begin, distance / 2);
    iterator it1 = std::partition(begin, end, [&p](const auto& v){ return v < *p;});
    iterator it2 = std::partition(it1, end, [&p](const auto& v) { return !(v > *p);});

    std::thread t1(qSort<Iterator>, begin, middle1);
    std::thread t2(qSort<Iterator>, middle2, end);

    t1.join();
    t2.join();
}

但这显然远非最佳实现。线程数将是log(n)。

问题:如何正确实现多线程快速排序算法?您可以编写一个限制线程数的类并将其传递给函数,但标准实现std::sort可以在多个线程中执行,而它的签名不会改变,我想实现类似的东西。

c++
  • 2 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2021-12-29 12:28:20 +0000 UTC

MAKEWORD 是如何工作的?

  • 2

头文件minwindef.h包含以下宏:

 #define MAKEWORD(a, b)      ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))

很明显他做了什么:他从两个字节收集 - 两个字节。

我的问题是:为什么要采取这么多行动?为什么在第一部分中首先转换为DWORD_PTR然后按位执行И,在第二部分中它是相似的:只WORD需要转换为和移位。

如果我而不是这样的宏写这个:

 BYTE a = 0x60;
 BYTE b = 0x20;
 WORD word = ((WORD)a | ((WORD)b) << 8);

这是正确的吗?

c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2021-12-18 20:30:14 +0000 UTC

在返回非void的函数中调用带有error no return语句的函数的后果是什么?

  • 3

有这个代码:

void func1()                                                                                                                                                                                                       
{                                                                                                                                                                                                                  
     std::cout << "func1" << std::endl;                                                                                                                                                                         
}                                                                                                                                                                                                                  
                                                                                                                                                                                                               
void func2()                                                                                                                                                                                                       
{                                                                                                                                                                                                                  
    std::cout << "func2" << std::endl;                                                                                                                                                                         
}                                                                                                                                                                                                                  
                                                                                                                                                                                                               
                                                                                                                                                                                                               
bool func3()                                                                                                                                                                                                       
{                                                                                                                                                                                                                  
    std::cout << "func3" << std::endl;                                                                                                                                                                         
    func1();                                                                                                                                                                                                   
    func2();                                                                                                                                                                                                   
}                                                                                                                                                                                                                  
                                                                                                                                                                                                               
                                                                                                                                                                                                               
int main(int argc, char* argv[])                                                                                                                                                                                   
{                                                                                                                                                                                                                  
      func3();                                                                                                                                                                                                   
      return 0;                                                                                                                                                                                                  
}                                                                                                                                                                                                                  
  

正如你在函数中看到的,bool func3()错误是:函数没有返回值。如果你编译这个程序:

 g++ -O2 main.cpp

然后我们得到以下行为

func3
func1
func2
func3
func1
func2
Ошибка сегментирования (стек памяти сброшен на диск)

问题:发生了什么?为什么函数被调用func3两次?以及为什么会出现分段错误,据我了解,只有在内存处理不正确时才会出现这样的错误。

在汇编程序中它看起来像这样(为简洁起见,我将输出删除到流中,行为被保留):

    .file   "main.cpp"
    .text
    .p2align 4
    .globl  _Z5func1v
    .type   _Z5func1v, @function
_Z5func1v:
.LFB0:
    .cfi_startproc
    endbr64
    ret
    .cfi_endproc
.LFE0:
    .size   _Z5func1v, .-_Z5func1v
    .p2align 4
    .globl  _Z5func2v
    .type   _Z5func2v, @function
_Z5func2v:
.LFB5:
    .cfi_startproc
    endbr64
    ret
    .cfi_endproc
.LFE5:
    .size   _Z5func2v, .-_Z5func2v
    .section    .text.unlikely,"ax",@progbits
    .globl  _Z5func3v
    .type   _Z5func3v, @function
 _Z5func3:
 .LFB2:
    .cfi_startproc
    endbr64
    .cfi_endproc
 .LFE2:
    .size   _Z5func3v, .-_Z5func3v
    .globl  main
    .type   main, @function
  main:
  .LFB3:
    .cfi_startproc
    endbr64
    .cfi_endproc
  .LFE3:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0"
    .section    .note.GNU-stack,"",@progbits
    .section    .note.gnu.property,"a"
    .align 8
    .long    1f - 0f
    .long    4f - 1f
    .long    5
  0:
    .string  "GNU"
  1:
    .align 8
    .long    0xc0000002
    .long    3f - 2f
  2:
    .long    0x3
  3:
    .align 8
  4:

有趣的是,如果您在没有优化的情况下进行编译,那么程序将正常工作。

g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2021-11-27 20:28:53 +0000 UTC

通过 make_shared 和 new 创建一个 shared_ptr

  • 2

在以下情况下创建std::shared_ptrviastd::make_shared可能很有用:

boo(std::shared_ptr<Bar>(new Bar), foo());

foo如果抛出异常,这里可能会有泄漏,并且

boo(std::make_shared<Bar>(), foo());

消除内存泄漏。

问题:一般来说,例如

 std::shared_ptr<Bar> pBar(new Bar);

好用new还是好用std::make_shared?

c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2021-11-19 10:55:42 +0000 UTC

通过 gdb 在 QtCreator 中显示变量

  • 1

gdb 调试器不显示类型变量的内容std::string

在此处输入图像描述

此外,如果您在控制台中查看 gdb,它会显示所有内容:

 milai@milai:~/projects/test_project/build/bin$ gdb ./test_project 
 GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1
 Copyright (C) 2020 Free Software Foundation, Inc.
 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 This is free software: you are free to change and redistribute it.
 There is NO WARRANTY, to the extent permitted by law.
 Type "show copying" and "show warranty" for details.
 This GDB was configured as "x86_64-linux-gnu".
 Type "show configuration" for configuration details.
 For bug reporting instructions, please see:
 <http://www.gnu.org/software/gdb/bugs/>.
 Find the GDB manual and other documentation resources online at:
     <http://www.gnu.org/software/gdb/documentation/>.

 For help, type "help".
 Type "apropos word" to search for commands related to "word"...
 Reading symbols from ./test_project...
 (gdb) list
 1  #include <string>
 2  #include <iostream>
 3  
 4  int main(int argc, char* argv[])
 5  {
 6      const std::string str = "abc";
 7      std::cout << str << std::endl;
 8      return 0;
 9  }
 (gdb) b 7
 Breakpoint 1 at 0x12bb: file /home/milai/projects/test_project/main.cpp, line 7.
 (gdb) r
 Starting program: /home/milai/projects/test_project/build/bin/test_project 

 Breakpoint 1, main (argc=1, argv=0x7fffffffdec8) at /home/milai/projects/test_project/main.cpp:7
 7      std::cout << str << std::endl;
 (gdb) info locals 
 str = "abc"
 (gdb) c
 Continuing.
 abc
 [Inferior 1 (process 40257) exited normally]
 (gdb) quit
 milai@milai:~/projects/test_project/build/bin$ 

可能是什么问题呢?

环境:

  • Ubuntu 20.04.1
  • qtcreator:4.11.0
  • gdb:9.1
  • g++ 9.3.0
c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-09-08 20:27:39 +0000 UTC

未调用移动构造函数

  • 1

有这么一堂课

 class A
 {
 public:
    A(): _size(0), _value(nullptr)
    {
        std::cout << "A() "<< this << std::endl;
    }
    A(const int size) : _size( size ), _value( new char[size] )
    {
        std::cout << "A( const int ) " << this << std::endl;
        for (int i = 0; i < _size; ++i)
            _value[i] = 'a' + i;
    }

    ~A()
    {
        std::cout << "~A() " << this << std::endl;
        if (_value)
           delete[] _value;
    }

    A( A&& a ):_size(0), _value(nullptr)
    {
        std::cout << "A( A&& ) "<< this << std::endl;
    
        std::swap( _size, a._size );
        std::swap( _value, a._value );
    }

    A& operator=( A&& a )
    {
         std::cout << "operator=( A&& ) "<< this << std::endl;

        std::swap( _size, a._size );
        std::swap( _value, a._value );
     
        return *this;
    }

    A( const A& a)
    {
         std::cout << "A( A& ) "<< this << std::endl;

        _size = a._size;
        _value = new char[_size];

        memcpy( _value, a._value, sizeof( char ) * _size );
    }
    A& operator=( const A& a)
    {
         std::cout << "operator=( const A& ) " << this << std::endl;
    
        _size = a._size;

        if (_value)
            delete _value;

        _value = new char[_size];

        memcpy( _value, a._value, sizeof( char ) * _size );
        return *this;
    }

 private:
    int _size; 
    char* _value;
 };

还有几个功能

A f1(int size)
{
    return A(size);
}

A foo( A&& a )
{
    return A( a );
}

执行此代码时:

 int main()
 {
      A a2 = foo( f1( 5 ) );
      return 0;
 }

输出如下:

 A( const int ) 0050F6E4
 A( A& ) 0050F7B4
 ~A() 0050F6E4
 ~A() 0050F7B4

也就是说,不调用移动构造函数。问题是为什么以及如何让它被调用?

c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-08-13 20:37:37 +0000 UTC

使用 ssl 加密创建 grpc 服务器

  • 1

我创建了一个 grpc 服务器:

grpc::ServerBuilder builder;
grpc::SslServerCredentialsOptions credential_options;
credential_options.force_client_auth = true;

const std::string private_key = read_file("server.key");
const std::string cert_chain =  read_file("server.crt");
credential_options.pem_key_cert_pairs.push_back({private_key, cert_chain});

auto channel_credentials = grpc::SslServerCredentials( credential_options );
builder.AddListeningPort(StateService::instance().ipAddress(), channel_credentials);
builder.RegisterService(grpcLocalService_.get());
server_ = builder.BuildAndStart();

我用脚本创建了一个密钥和一个证书:

mypass="pass123"

echo Generate server key:
openssl genrsa -passout pass:$mypass -des3 -out server.key 4096

echo Generate server signing request:
openssl req -passin pass:$mypass -new -key server.key -out server.csr -subj  "/C=US/ST=CA/L=SanFrancisco/O=Google/OU=youtube/CN=localhost"

echo Self-sign server certificate:
openssl x509 -req -passin pass:$mypass -days 365 -in server.csr -signkey server.key -set_serial 01 -out server.crt

echo Remove passphrase from server key:
openssl rsa -passin pass:$mypass -in server.key -out server.key

rm server.csr

当我运行应用程序时,我得到以下信息:

E0813 19:24:39.571705892 21058 ssl_transport_security.c:628] 证书链文件无效。

E0813 19:24:39.571727037 21058 security_connector.c:893] 握手器工厂创建失败,出现 TSI_INVALID_ARGUMENT。

E0813 19:24:39.571736766 21058 server_secure_chttp2.c:96] {"created":"@1597321479.571730594","description":"无法使用 Ssl 类型的凭据创建安全服务器。","file":"src/core/ ext/transport/chttp2/server/secure/server_secure_chttp2.c","file_line":75,"security_status":1}

我是否正确理解grpc::SslServerCredentialsOptions::PemKeyCertPair您需要传递文件的内容.key和.crt而不是文件名?如果是这样,应该如何阅读它们?

 -----BEGIN CERTIFICATE-----
 MIIFMDCCAxgCAQEwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCVVMxCzAJBgNV
 ...// лишние строки убрал для краткости
 BAgMAkNBMQ4wDAYDVQQHDAVUb21zazEOMAwGA1UECgwFRWxlc3kxDjAMBgNVBAsM
 -----END CERTIFICATE-----

是否跳过第一行和最后一行?

但无论如何,错误仍然是一样的。 Handshaker factory creation failed with TSI_INVALID_ARGUMENT.

c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-01-28 23:30:00 +0000 UTC

自定义分配器

  • 0

有这样一个分配器:

template<class T>
class Allocator
{   
public:
    using value_type = T;

    Allocator() noexcept {}

    template<class _Other>
    Allocator(const Allocator<_Other>&) noexcept
    {   
        //std::cout << typeid(_Other).name() << std::endl;
    }

    void deallocate(T* const ptr, const size_t count)
    {   
        std::cout << "Allocator::deallocate " << ptr << std::endl;
        std::free(ptr);
    }

    T* allocate(const size_t count)
    {   
       if(count > std::numeric_limits<size_t>::max() / sizeof(T) )
            throw std::bad_alloc();

        void* ptr = std::malloc(count);
        std::cout << "Allocator::allocate " << ptr << std::endl;
        return static_cast<T*>(ptr);
    }
};

class A
{
public:

    A()
    {
        std::cout << "A() " << this << std::endl;
    }

    ~A()
    {
        std::cout << "~A() " << this  << std::endl;
    }
};

这就是我使用它的方式:

int main(int argc, char* argv[])
{
    std::vector<A, Allocator<A>> vec;
    vec.push_back(A());
    return 0;
}

这是程序输出的内容:

Allocator::allocate 00ED7A48
A() 00DCFA33
Allocator::allocate 00ED7DA0
~A() 00DCFA33
~A() 00ED7DA0
Allocator::deallocate 00ED7DA0
Allocator::deallocate 00ED7A48

为什么要调用构造函数A()?通过cppreference std::malloc判断不调用构造函数。

我不太明白为什么程序会因消息而崩溃

HEAP_CORRUPTION DETECTED:在 0x00ED7A48 CRT 的 Normal block(#152) 后检测到应用程序在堆缓冲区结束后写入内存;

尝试删除第二个对象时?

c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-11-20 15:32:14 +0000 UTC

Astra Linux 中的 GUI 问题

  • 2

有一个继承自 的类QMainWindow,在其中我设置了两个QDockWidget和中央小部件:

QWidget* centralWidget = new TreeWidget(this);
setCentralWidget(centralWidget);
QDockWidget* treeDockWidget = new QDockWidget( this );
treeDockWidget->setWidget( new TreeWidget );
treeDockWidget->setAllowedAreas( Qt::DockWidgetArea::AllDockWidgetAreas );
addDockWidget( Qt::DockWidgetArea::LeftDockWidgetArea, treeDockWidget );


QDockWidget* editorWidget = new QDockWidget( this );
editorWidget->setWidget( new EditorWidget( this ) );;
editorWidget->setAllowedAreas( Qt::DockWidgetArea::AllDockWidgetAreas );
addDockWidget( Qt::DockWidgetArea::LeftDockWidgetArea, editorWidget );

当任何小部件被拉伸时,它会任意将自身调整为默认大小。此行为仅出现在 Astra Linux 上。在 Ubuntu 18.04 上一切正常。

可能是什么原因?

在此处输入图像描述

c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-02-22 13:30:34 +0000 UTC

Qt 显示树的根元素

  • 0

我想创建自己的树模型,结果是这样的:

在此处输入图像描述

如何使根元素显示出来?

class TreeItem
{
public:
    explicit TreeItem(const QString &data, TreeItem* parent = 0);
    ~TreeItem();

    void appendChild(TreeItem *child);
    void setParent(TreeItem *parent);


    TreeItem *child(int row);
    int childCount() const;
    QString data() const;
    int row() const;
    TreeItem *parentItem();

private:
    QList<TreeItem*> _childItems;
    QString _data;
    TreeItem* _parentItem;
};

class TreeModel : public QAbstractItemModel
{
public:
    explicit TreeModel( const QString &data, QObject *parent = 0 );
    ~TreeModel();

    QVariant data( const QModelIndex &index, int role ) const override;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
    Qt::ItemFlags flags( const QModelIndex &index ) const override;
    QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
    QModelIndex parent( const QModelIndex &index)  const override;
    int rowCount( const QModelIndex &parent = QModelIndex() ) const    override;
    int columnCount( const QModelIndex &parent = QModelIndex() ) const override;

private:

    TreeItem* _rootItem;
};


QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent ) const
{
    qDebug() << "TreeModel::index";
    if ( !hasIndex(row, column, parent) )
        return QModelIndex();

    TreeItem* parentItem;

    if ( !parent.isValid() )
        parentItem = _rootItem;
    else
        parentItem = static_cast<TreeItem*>( parent.internalPointer() );

    TreeItem* childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex TreeModel::parent(const QModelIndex &index) const
{
    qDebug() << "TreeModel::parent";
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
    TreeItem *parentItem = childItem->parentItem();

    if (parentItem == _rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}


MainWindow::MainWindow()
{
    mainWindow.setupUi(this);

    TreeModel* model = new TreeModel("abc");

    mainWindow.treeView->setModel(model);
}
c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-02-02 18:00:45 +0000 UTC

使用 COM 端口。冲洗和丢弃之间的区别

  • 2

Windows 有一个功能PurgeComm

丢弃指定通信资源的输出或输入缓冲区中的所有字符。它还可以终止对资源的未决读或写操作。

并且有一个功能FlushFileBuffers

刷新指定文件的缓冲区并将所有缓冲数据写入文件。

这里一切都清楚PurgeComm了,清除缓冲区,但FlushFileBuffers强制将数据从缓冲区刷新到文件。

现在的Linux。int tcflush(int fd, int queue_selector);

man termios产生以下内容:

tcflush() 根据 queue_selector 的值,丢弃写入 fd 引用的对象但未传输的数据,或接收但未读取的数据:

TCIFLUSH - 刷新接收但未读取的数据。

TCOFLUSH - 刷新写入但未传输的数据。

TCIOFLUSH - 刷新接收但未读取的数据和写入但未传输的数据。

也就是函数的描述说是discards,flags的描述是 flush

那么她最终做了什么?从缓冲区中删除数据或将其刷新到文件中?

linux
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-01-30 18:46:32 +0000 UTC

COM 端口仿真

  • 3

我在 VirtualBox 上安装了 ubuntu 16.04。机器本身有一个物理 com 端口,它在“主机设备”模式下被扔到 VirtualBox 中,如下所示:

在此处输入图像描述

我还在“禁用”模式下启用了 2 个端口:

在此处输入图像描述

因此,这些端口是在 ubuntu 上定义的。(但据我了解,我只能使用一个)

 $ dmesg | grep tty
[    0.004000] console [tty0] enabled
[    0.772403] 00:02: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[    0.794717] 00:03: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
[    0.816355] 00:04: ttyS2 at I/O 0x3e8 (irq = 4, base_baud = 115200) is a 16550A

问题是:我是否可以这样做,以便我可以在不连接任何设备(我只需要一个回声)的情况下从 com 端口(如这里)写入和读取,并且无需求助于任何拐杖,例如将回形针插入端口以关闭 TX-RX。

你能帮我解决这个问题吗socat?据我了解,您可以使用它建立从一个端口到另一个端口的桥梁,但我对它的设置感到困惑,如果有人告诉我正确的线路,我将不胜感激。

或者socat它不适合这个目的,我需要别的东西?

linux
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-01-29 13:04:45 +0000 UTC

写入和读取 Linux COM 端口

  • 2

我想写入 com 端口并从中读取一定数量的字节。录制似乎没有问题,它不write返回错误。但是在阅读问题时:它read挂起。也就是说,港口什么都没有,但如果我以前做过,怎么可能write呢?或者它是否以其他方式工作?

int main(int argc, char* argv[])
{
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY /*| O_NDELAY*/);
    if (fd == -1)
    {
        std::cout << " Unable to open /dev/ttyS0" << std::endl;
        return 0;
    }

    // configure
    termios attr_old;
    termios attr;
    memset( &attr_old, 0, sizeof(termios) );
    memset( &attr, 0, sizeof(termios) );

    if ( tcgetattr(fd, &attr_old) )
    {
         std::cout << "Error: " << strerror(errno) << " from tcgetattr" << std::endl;
        return 0;
    }

    attr = attr_old;

    //Baud rate
    cfsetospeed(&attr, B9600);
    cfsetispeed(&attr, B9600);

    attr.c_cflag     &=  ~PARENB;            // Make 8n1
    attr.c_cflag     &=  ~CSTOPB;
    attr.c_cflag     &=  ~CSIZE;
    attr.c_cflag     |=  CS8;
    attr.c_cflag     |=  CREAD | CLOCAL;     // turn on READ & ignore ctrl lines
    attr.c_cflag     &=  ~CRTSCTS;           // no flow control

    attr.c_cc[VMIN]   =  1;                  // read doesn't block
    attr.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout


    // Make raw 
    cfmakeraw(&attr);

   // Flush Port, then applies attributes
    tcflush( fd, TCIFLUSH );

    if ( tcsetattr ( fd, TCSANOW, &attr ) != 0)
    {
        std::cout << "Error: " << strerror(errno) << " from tcsetattr" << std::endl;
        return 0;
    }

    //Write
    int nw = write(fd, "A\r", 2);
    if ( nw < 0)
    {
         std::cout << "Error: " << strerror(errno) << " from write" << std::endl;
         return 0;
    }

    //Read
    char buff[32];
    memset( &buff, '\0', sizeof(buff) );

    int nr = 0;
    int spot = 0;
    char ch = '\0';
    do 
    {
        nr = read(fd, &ch, 1);
        if (nr < 0 )
        {
              int er = errno;
              std::cout << "Error:  " << er << " " << strerror(er) << " from read" << std::endl;
              return 0;
        }
        sprintf(&buff[spot], "%c", ch);
        spot += nr;
    }
    while( ch != '\r' && nr > 0 );

    close(fd);

    return 0;
}
c++
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-11-19 12:14:51 +0000 UTC

检查连接是否建立在非阻塞连接上

  • 0

非阻塞连接正在进行中。在windows下,可以通过select判断socket何时建立,如果socket是可写的,则连接建立。linux下呢?初始化后,立即变为可写。因此,尝试向套接字写入内容将导致 SIGPIPE。

int sockfd = ::socket(AF_INET, SOCK_STREAM, 0);

int arg = ::fcntl(sockfd, F_GETFL);
long flags = arg & ~O_NONBLOCK;
flags |= O_NONBLOCK;
fcntl(sockfd, F_SETFL, flags);

struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(1111);
inet_aton("127.0.0.1", &dest.sin_addr);

int rc = ::connect(sockfd, (struct sockaddr* )&dest, sizeof(dest));

fd_set fdWrite;
FD_ZERO(&fdWrite);
FD_SET(sockfd, &fdWrite);

struct timeval tv;
tv.tv_sec  = 1;
tv.tv_usec = 0;

rc = ::select(int(sockfd) + 1, 0, &fdWrite, 0, &tv);
int er = errno;

return 0;
linux
  • 1 个回答
  • 10 Views
Martin Hope
Rikitikitavi
Asked: 2020-09-26 19:11:53 +0000 UTC

使用模板参数作为另一个类的模板参数

  • 3

有这个代码:

template< typename T>                                                                                                                                                                                              
class A                                                                                                                                                                                                            
{                                                                                                                                                                                                                  
public:                                                                                                                                                                                                            
  typedef std::map<int, typename T*>::const_iterator Const_iterator;                                                                                                                                               

}; 

g++ 7.3.0 抛出此错误:

main.cpp:8:36: error: template argument 2 is invalid
   typedef std::map<int, typename T*>::const_iterator Const_iterator;

是什么原因?

c++
  • 1 个回答
  • 10 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5