小编Ada*_*dam的帖子

在DLL中使用default关键字

default在DLL项目中使用关键字时,我遇到了一个非常奇怪的问题.在我的DLL项目(使用VS2013编译)中,我有以下类:

public class BaseClass<T>
{
    public T value;
    public bool enabled;

    public BaseClass ( T value = default(T), bool enabled = true )
    {
        this.value = value;
        this.enabled = enabled;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我在DLL项目中使用它,它可以很好地工作.我可以创建从这个基类派生的类而不会出现问题.但是,只要我尝试在另一个项目中使用DLL(使用Mono 2.0.0编译),从基类派生值类型会导致编译器错误.这个:

public class ChildClass : BaseClass<int>
{
}
Run Code Online (Sandbox Code Playgroud)

导致这个:

Assets/ChildClass.cs(8,14):错误CS1502:BaseClass <int> .BaseClass(int,bool)'的最佳重载方法匹配有一些无效的参数

Assets/ChildClass.cs(8,14):错误CS1503:参数#1' cannot convertnull'表达式为'int'类型

但是,具有值类型的基类可以在没有问题的字段中使用:

public class OtherClass
{
    public BaseClass<int> baseInt;
}
Run Code Online (Sandbox Code Playgroud)

我使用ILSpy查看了DLL并注意到了这一点:

public class BaseClass<T>
{
    public T value;
    public bool enabled;
    public BaseClass(T value = null, bool enabled = true) …
Run Code Online (Sandbox Code Playgroud)

c# mono default

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

当目标位于另一个AppDomain中时,托管回调未受管理的速度要慢得多

我正在使用委托从非托管代码调用托管代码.当我在默认的AppDomain中调用托管代码时,我每次调用的平均值为5.4ns.当我呼叫第二个AppDomain时,我每次呼叫的测量值为194ns.(默认VS2017 x86发布配置,不在调试器下运行).

调用不是默认的AppDomain时,为什么性能会低得多?由于我来自非托管方,它不了解AppDomains,我希望直接调用目标域.但是,性能打击意味着委托调用默认域然后编组到真实目标.我确实看到了UM2MDoADCallBack踩踏拆装的时候.它出现WrongAppDomain:UMThunkStub.asm中

如何防止这种不必要的封送并直接调用特定的AppDomain?

我用来测试它的代码如下.

#pragma unmanaged
#include <wtypes.h>
#include <cstdint>
#include <cwchar>

typedef void (__stdcall *ManagedUpdatePtr)();

struct ProfileSample
{
    static uint64_t frequency;
    uint64_t startTick;
    wchar_t* name;
    int count;

    ProfileSample(wchar_t* name_, int count_)
    {
        name = name_;
        count = count_;

        LARGE_INTEGER win32_startTick;
        QueryPerformanceCounter(&win32_startTick);
        startTick = win32_startTick.QuadPart;
    }

    ~ProfileSample()
    {
        LARGE_INTEGER win32_endTick;
        QueryPerformanceCounter(&win32_endTick);
        uint64_t endTick = win32_endTick.QuadPart;

        uint64_t deltaTicks = endTick - startTick;
        double nanoseconds = (double) deltaTicks / (double) frequency * 1000000000.0 / count;

        wchar_t …
Run Code Online (Sandbox Code Playgroud)

clr performance interop c++-cli

8
推荐指数
0
解决办法
199
查看次数

宽松的原子计数器安全吗?

根据 C++11 内存模型,以下代码是否保证返回计数器的预期值 (40,000,000)?(不限于 x86)。

\n\n
#include <atomic>\n#include <thread>\nusing namespace std;\n\nvoid ThreadProc(atomic<int>& counter)\n{\n    for (int i = 0; i < 10000000; i++)\n        counter.fetch_add(1, memory_order_relaxed);\n}\n\nint main()\n{\n    #define COUNT 4\n    atomic<int> counter = { 0 };\n    thread threads[COUNT] = {};\n\n    for (size_t i = 0; i < COUNT; i++)\n        threads[i] = thread(ThreadProc, ref(counter));\n\n    for (size_t i = 0; i < COUNT; i++)\n        threads[i].join();\n\n    printf("Counter: %i", counter.load(memory_order_relaxed));\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

特别是,宽松的原子是否会进行协调,使得两个线程不会同时读取当前值、独立地递增它,并且都写入其递增的值,从而有效地丢失其中一个写入?

\n\n

规范中的一些行似乎表明在上面的示例中计数器必须始终为 40,000,000。

\n\n
\n

[注意:指定 memory_order_relaxed …

c++ concurrency multithreading synchronization atomic

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

与放松的原子同步

我有一个分配器,它使用轻松的原子来跟踪当前分配的字节数.它们只是添加和减少所以我不需要线程之间的任何同步,除了确保修改是原子的.

但是,我偶尔会检查分配的字节数(例如,在关闭程序时),并且我想确保提交任何挂起的写入.我假设在这种情况下我需要一个完整的内存屏障,以防止在屏障之后移动任何先前的写入,并防止下一次读取在屏障之前移动.

问题是:在阅读之前确保放松原子写入的正确方法什么?我当前的代码是否正确?(假设函数和类型按预期映射到std库结构.)

void* Allocator::Alloc(size_t bytes, size_t alignment)
{
    void* p = AlignedAlloc(bytes, alignment);
    AtomicFetchAdd(&allocatedBytes, AlignedMsize(p), MemoryOrder::Relaxed);
    return p;
}

void Allocator::Free(void* p)
{
    AtomicFetchSub(&allocatedBytes, AlignedMsize(p), MemoryOrder::Relaxed);
    AlignedFree(p);
}

size_t Allocator::GetAllocatedBytes()
{
    AtomicThreadFence(MemoryOrder::AcqRel);
    return AtomicLoad(&allocatedBytes, MemoryOrder::Relaxed);
}
Run Code Online (Sandbox Code Playgroud)

以及上下文的一些类型定义

enum struct MemoryOrder
{
    Relaxed = 0,
    Consume = 1,
    Acquire = 2,
    Release = 3,
    AcqRel = 4,
    SeqCst = 5,
};

struct Allocator
{
    void*  Alloc            (size_t bytes, size_t alignment);
    void   Free             (void* p);
    size_t GetAllocatedBytes();

    Atomic<size_t> …
Run Code Online (Sandbox Code Playgroud)

c++ concurrency multithreading atomic

7
推荐指数
2
解决办法
300
查看次数

将接受braced-init-list并推断长度的Array类

之前有人问过,但我很想知道新的C++标准是否有任何改变.任何当前或未来的标准都是可以接受

:无论如何都要创建一个可以用braced-init-list初始化的Array类,而不必手动指定数组长度,元素存储在堆栈中,并且不需要'make_array'函数.

template<class T, size_t N>
struct Array
{
    T items[N];
};

Array<int> foo = { 1, 2, 3 };
Run Code Online (Sandbox Code Playgroud)

由于initializer_list没有模板的大小,使用它的构造函数将无法完成这项工作.C++ 17中的演绎指南几乎可以工作,但您必须省略类型参数,并且所有项目必须具有完全相同的类型

Array foo = { 1, 2, 3 }; // Works
Array<int> foo = { 1, 2, 3 }; // Doesn't work
Array foo = { 1.0, 2.0, 3.0f }; //Doesn't work
Run Code Online (Sandbox Code Playgroud)

采用c数组的构造函数似乎不起作用,因为它initializer_list不会转换为c数组.

braced-init-listT[N]在发生int foo[] = { 1, 2, 3 };纯粹的编译器魔术不能在代码被复制?

编辑:这个问题的精神是关于上面的确切语法.没有make_array,没有额外的模板参数,显式项类型,没有双括号,没有动态分配.如果一个普通的数组需要一堆现代的C++ tomfoolery并且仍然无法支持标准语法,那么在我看来这只是一个糟糕的工程权衡.

c++ initializer-list template-argument-deduction c++17 c++20

7
推荐指数
2
解决办法
264
查看次数

Visual Studio 调用堆栈总是偏离一行

我注意到 VS 中的调用堆栈似乎总是偏离一行。一旦我进入一个函数,我刚刚离开的堆栈帧的行号就会增加并指向下一个非空行。然后,如果我双击“调用堆栈”窗口中的该框架,它确实会将我带到我实际所在的函数调用之后的某行。我已在 VS2015 和 VS2017 的空项目中重新存储了此内容(调试版本)。

在下图中,您会注意到第二个堆栈帧指示第 17 行,这是调试器实际停止的 Log() 调用下方几行的返回。

这是一个微不足道的重现,但我在实际项目中经常看到这种情况,并且我不记得在过去几天之外遇到过这个问题。

任何人都知道可能是什么原因造成的?

在此输入图像描述

visual-studio visual-c++ visual-studio-debugging

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

将DataContext设置为XAML中的当前代码隐藏对象

我正在尝试将UserControl的DataContext设置为UserControl的代码隐藏类.从代码隐藏方面来看,这很容易做到:

public partial class OHMDataPage : UserControl
{
    public StringList Stuff { get; set; }

    public OHMDataPage ()
    {
        InitializeComponent();

        DataContext = this;
    }
}
Run Code Online (Sandbox Code Playgroud)
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Class="LCDHardwareMonitor.Pages.OHMDataPage">

    <ScrollViewer>
        <ListBox ItemsSource="{Binding Stuff}" />
    </ScrollViewer>

</UserControl>
Run Code Online (Sandbox Code Playgroud)

但是,我怎样才能完全从XAML端和UserControl级别执行此操作?如果我这样做(并DataContext = this;从代码隐藏中删除)它适用于子节点:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Class="LCDHardwareMonitor.Pages.OHMDataPage">

    <ScrollViewer
        DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
        <ListBox ItemsSource="{Binding Stuff}" />
    </ScrollViewer>

</UserControl>
Run Code Online (Sandbox Code Playgroud)

我真的很想了解如何在UserControl本身上执行此操作.我希望这可行:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Class="LCDHardwareMonitor.Pages.OHMDataPage"
    DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">

    <ScrollViewer>
        <ListBox ItemsSource="{Binding Stuff}" />
    </ScrollViewer>

</UserControl>
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.

c# wpf xaml

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

未受管理的x86和x64中的托管互操作性能

在我的测试中,我看到在编译x64而不是x86时,非托管到托管互操作的性能成本.导致这种放缓的原因是什么?

我正在测试不在调试器下运行的发布版本.该循环是100,000,000次迭代.

在x86中,我每次互操作平均测量8ns,这似乎与我在其他地方看到的相匹配.Unity的x86互操作是8.2ns.一篇微软文章和Hans Passant都提到了7ns.8ns在我的机器上是28个时钟周期,这似乎至少是合理的,但我不知道是否可能更快.

在x64中,我每次互操作平均测量17ns.我找不到任何人提到x86和x64之间的区别,甚至提到他们在给出时间时指的是什么.Unity的x64互操作时钟约为5.9ns.

常规函数调用(包括非托管C++ DLL)的平均成本为1.3ns.这在x86和x64之间没有显着变化.

下面是我测量它的最小C++/CLI代码,虽然我在实际项目中看到相同的数字,它包含一个调用C++/CLI DLL管理端的本机C++项目.

#pragma managed
void
ManagedUpdate()
{
}


#pragma unmanaged
#include <wtypes.h>
#include <cstdint>
#include <cwchar>

struct ProfileSample
{
    static uint64_t frequency;
    uint64_t startTick;
    wchar_t* name;
    int count;

    ProfileSample(wchar_t* name_, int count_)
    {
        name = name_;
        count = count_;

        LARGE_INTEGER win32_startTick;
        QueryPerformanceCounter(&win32_startTick);
        startTick = win32_startTick.QuadPart;
    }

    ~ProfileSample()
    {
        LARGE_INTEGER win32_endTick;
        QueryPerformanceCounter(&win32_endTick);
        uint64_t endTick = win32_endTick.QuadPart;

        uint64_t deltaTicks = endTick - startTick;
        double nanoseconds = (double) deltaTicks / (double) frequency * 1000000000.0 / count; …
Run Code Online (Sandbox Code Playgroud)

performance 64-bit interop c++-cli

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

operator-&gt; 用于返回临时值的迭代器

我有一个数据结构,它本质上是一个哈希表。出于缓存原因,键和值分开存储。我有一个迭代器,它遍历容器并在取消引用时返回键和值对。

但是,我在让迭代器像其他人一样运行时遇到了一些麻烦。特别是与operator->. 这是我到目前为止所拥有的:

struct KeyValuePair
{
    KeyValuePair(const int& key, int& value) : key(key), value(value) {}

    const int& key;
    int& value;
};

struct Iterator
{
    KeyValuePair operator*() { return KeyValuePair(*keys, *values); }

    // TODO: Implement this
    //KeyValuePair* operator->() { return ... }

    int* keys = nullptr;
    int* values = nullptr;
};
Run Code Online (Sandbox Code Playgroud)

这适用于 range-for 和显式取消引用迭代器

auto it = container.begin();
KeyValuePair pair = *it;
Run Code Online (Sandbox Code Playgroud)

但它不适用于“通过”迭代器,因为我没有 operator->

auto it = container.begin();
int& value = it->value;
Run Code Online (Sandbox Code Playgroud)

我不知道如何实现operator->这个迭代器。我的第一个想法是KeyValuePair在迭代器中粘贴 a并返回一个指向它的指针,但是没有诡计就无法重新设置引用。

比我更聪明的人有什么提示吗?

c++ iterator c++17

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