有一大类问题都可以划分到,该程序采用HASP加密

如何解决远程桌面访问HASP NOT Found的问题,一大票问题都可以归结于

图片 3

如何解决远程桌面访问HASP NOT Found的问题

如何解决远程桌面访问HASP NOT Found的问题

背景:

我在进行远程桌面访问时,点击其中一个程序,该程序采用HASP加密。发现无法启动该程序,程序报错,提示Hasp
not found。HASP是我插到远程服务器上的

HASP的加密狗。

解决方法:

mstsc /admin的方式打开远程访问终端。


图片 1


NOT Found的问题
如何解决远程桌面访问HASP NOT Found的问题 背景:
我在进行远程桌面访问时,点击其中一个程序,该…

在程序的世界里,有一大类问题都可以划分到404 NOT Found的类别里,一大票问题都可以归结于查表找不到

构造函数

class Dispatch{
  Dispatch(int i){}
};
Dispatch a;// Compile Error

最早学C++的时候,总是被这个问题搞的莫名奇妙,原来C++编译器会给一个class偷偷添加默认构造函数
但是,如果用户自己定义了一个,则编译器不再提供默认构造函数。此时上述代码要通过的话需要我们
自己给Dispatch添加一个无参数构造函数,方可通过。

class Dispatch{
  Dispatch(){}
  Dispatch(int i){}
};
void DoSomething(){
  Dispatch a;// Compile Error
}

我们可以说

404 NOT Found:您调用的构造函数不存在
  • 添加explicit关键字的单参数构造函数,刻意让想要隐式转换并调用构造函数的时候,404
    NOT Found…:
    see:what does the explicit keyword in c
    mean

  • 至于当时为什么我会在没有无参构造函数的时候写Dispatch a;这样的语句,应该是以为所有的变量都可以这样声明吧。可惜C++里这里的行为就是在栈上分配了内存,调用了无参构造函数。

  • 默认构造函数无参构造函数是两个概念。默认行为往往是坑,一旦使用方的需求和默认行为不匹配,而使用者又对默认行为不清楚,就会出现各种诡异的问题。
    see:Do the parentheses after the type name make a difference with
    new?

  • 比如说当使用STL的时候,class的拷贝构造函数、赋值操作符,小于比较操作符等都在模板算法里被使用,一个学习STL的新手一定会在不了解模板的duck type interface原理时被这种默认行为坑到。
    see:What is The Rule of
    Three?

  • C++03里构造函数不能调用别的构造函数,因为class还没构造完呢。。C++11添加了语法糖,支持了…

数组名和指针

C的数组和指针的区别在于,数组名只是数组起始地址的别名,编译器编译后就被替换成了数组的首地址,而一个指向数组的指针则是一个变量,是运行期行为。下面的代码:

char array_place[100] = "don't panic";
char* ptr_place = "don't panic";

int main()
{
    char a = array_place[7];
    char b = ptr_place[7];

    return 0;
}

编译后的汇编是

    char a = array_place[7];

0041137E  mov  al,byte ptr [_array_place+7 (417007h)]
00411383  mov  byte ptr [a],al

    char b = ptr_place[7];

00411386  mov  eax,dword ptr [_ptr_place (417064h)]
0041138B  mov  cl,byte ptr [eax+7]
0041138E  mov  byte ptr [b],cl

数组名示意图:
图片 2
指向数组的指针示意图:
图片 3

所以,而一个函数的数组参数

void foo(char arr_arg[], char* ptr_arg)
{
    char a = arr_arg[7];
    char b = ptr_arg[7];
}

编译后是:

char a = arr_arg[7];

00412DCE  mov  eax,dword ptr [arr_arg]
00412DD1  mov  cl,byte ptr [eax+7]
00412DD4  mov  byte ptr [a],cl

    char b = ptr_arg[7];

00412DD7  mov  eax,dword ptr [ptr_arg]
00412DDA  mov  cl,byte ptr [eax+7]
00412DDD  mov  byte ptr [b],cl

则是一模一样的,这是因为编译的时候,函数并没有被调用,所以编译器并不知道arr_arg的实际地址是什么,所以编译器就只能把它向指针一样处理。
这部分内容源自:are pointer and arrays equivalent in
c?

我们可以说

404 NOT Found:函数编译时,数组的实际地址找不到,请看:https://lkml.org/lkml/2015/9/3/428,“because array arguments in C don't
actually exist”

野指针

一个class的指针成员变量,如果未被初始化,则是一个野指针,它不是NULL。
于是在运行的时候,它指向的内存(并不是有效的该类数据)被解码成这个类的数据,此时实际上是乱码的。
这样的乱码数据运行下去,就会有运行期的未定义行为。

我们可以说

404 NOT Found:野指针,指针指向的数据并不是有效的对象数据,您要的数据不存在

又:函数里返回局部栈上变量的引用或者指针,函数调用完的时候,函数的Stack被ret掉,局部变量的引用或指针就指向了已经被ret了的内存,
在后续的stack变来边去的时候,那块内存的数据早就不是原来的了。

404 NOT Found:您指向的栈地址的数据早就不是当初那个东西了...

此处有人还长篇大论:Can a local variable’s memory be accessed outside
its
scope?

未定义符号

C/C++
编译的时候,出现未定义符号,原因可能是这个符号所在的头文件并没有被包含。
为了找到它,可能的行为包括

  1. 指定Include查找目录
  2. 添加必要的头文件

我们可以说

404 NOT Found:符号所定义的文件找不到

未解决的符号

C/C++链接的时候,出现未解决的符号,原因可能是这个符号的定义虽然在编译的时候找到了,但是链接的时候没发现它的实现。
为了找到它,可能的行为包括

  1. 比如说函数在头文件里实现了,在.c或者.cpp里却没有实现,那么实现它
  2. 添加Lib查找的目录
  3. 添加需要连接的Lib文件

我们可以说

404 NOT Found:符号没有被实现或者找不到obj,或者找不到库(一堆obj的合集)

威廉希尔公司 ,又:它的反面是同一个符号有多个实现的版本,比如多个同时链接了多个不同实现的C运行时。此时不是找不到,而是找到了多个不知道用哪个,解决也很简单,明确指定要用的是哪个。
又:还有一种是同时只有多个弱符号,没有一个强符号,则不知道用哪个。

这两种情况,可以说

404 NOT Found: 有多个版本,找不到一个最强的来用

模板的具现化

#define type_zero 0
#define type_one 1
#define type_two 2

template <int type>
struct trait;          //Declare

template <>
struct trait<type_zero>{ //A
  enum {value=0}; 
};

template <>
struct trait<type_one>{ //B
  enum {value=1};
};

template <>
struct trait<type_two>{ //B
  enum {value=2};
}

void DoSomething(){
  std::cout<<trait<2>::value<<std::endl;//(1) 
  std::cout<<trait<3>::value<<std::endl;//(2),Compile Error
}

对于(1):

  1. 编译器尝试使用A版本具现化,不匹配,错误A,先不出错,下一步;
  2. 编译器尝试使用B版本具现化,不匹配,错误B,先不出错,下一步;
  3. 编译器尝试使用C版本具现化,匹配,忽略错误A和错误B

对于(2):

  1. 编译器尝试使用A版本具现化,不匹配,错误A,先不出错,下一步;
  2. 编译器尝试使用B版本具现化,不匹配,错误B,先不出错,下一步;
  3. 编译器尝试使用C版本具现化,不匹配,错误C,抛出编译错误。

如果编译器在错误A的时候就直接编译错误,那就没什么好说了,但编译器会尝试找重载的模板尝试具现化,直到所有的尝试都失败时才认为是真的失败了。

我们可以说

404 NOT Found:找不到可以具现化的模板

美高梅集团4688 ,在尝试具现化的过程中遇到失败的情况先不抛出的特性也被起了个名字:

SFINAE: "Substitution Failure Is Not An Error"

再来一个例子:

struct example
{
    template <typename T>
    static void pass_test(typename T::inner_type); // A

    template <typename T>
    static void pass_test(T); // B

    template <typename T>
    static void fail_test(typename T::inner_type); // C
};

int main()
{
    // enumerates all the possible functions to call: A and B
    // tries A, fails with error; error withheld to try others
    // tries B, works without error; previous error ignored
    example::pass_test(5);

    // enumerates all the possible functions to call: C
    // tries C, fails with error; error withheld to try others
    // no other functions to try, call failed: emit error
    example::fail_test(5);
}

see: Substitution Failure Is Not An
Error

竞态条件

class Dispatch{

public:
  void AddObserver(Observerable* o){
      AutoSpinLock lock(m_lock);
      ...  
  }
  void RemoveObserver(Observerable* o){
      AutoSpinLock lock(m_lock);
      ...
  }
  void NotifyObservers(){
     AutoSpinLock lock(m_lock);
     Observers::iterator it=m_observers.begin();
     while(it!=m_observers.end()){
       Observer* o = *it;
       o.DoSomething();
       ++it;
     }
  }
private:
  typedef std::vector<Observerable*> Observers;   
  SpinLock m_lock;
  Observers m_observers;
}

发生的情况

  1. 线程A:NotifyObservers。
  2. 线程B:Observer要delete之前,调用Remove,成功,然后就析构自己。
  3. 此时A线程的DoSomething还在过程中,崩溃。

此时我们可以说

404 NOT Found:您要通知的对象已被析构...

解决的办法就是用引用计数智能指针+弱引用智能指针

class Dispatch{

public:
  void AddObserver(weak_ptr<Observerable> o){
      AutoSpinLock lock(m_lock);
      ...  
  }
  void RemoveObserver(weak_ptr<Observerable> o){
      AutoSpinLock lock(m_lock);
      ...
  }
  void NotifyObservers(){
     AutoSpinLock lock(m_lock);
     Observers::iterator it=m_observers.begin();
     while(it!=m_observers.end()){
       shared_ptr<Observer> obj(it->lock());// 如果存活,增持,避免被析构
       if(obj){
         o.DoSomething();
         ++it;
       }else{
         it = observers.erase(it);
       }
     }
  }
private:
  typedef std::vector<std::weak_ptr<Observerable>> Observers;   
  SpinLock m_lock;
  Observers m_observers;
}

see:Linux多线程服务端编程

如果不用智能指针,不带引用计数,那么,可以在NotifyObservers的时候,不立刻执行DoSomething,而是投递到目标线程去执行。假设Observer的工作线程是B,Dispatch在线程A,则NotifyObservers可以投递到线程B,在线程B才做真正的遍历触发,则保证Observer的Add、Remove、Find都在线程B,从而避免线程问题。

切换脚本语言

一个同学写了一段时间的lua代码

for i,v in pairs(nodes) do
  --//do something
end

有一天切换成到Python环境下写代码,同样遍历字典

for i,v in pairs(nodes):
  ## do something

404 NOT Found:paris是个什么鬼...

去掉

for i,v in nodes:
  ## do something

404 NOT Found:没有迭代器...

好吧:

for i,v in nodes.items():
  ## do something